dnscontrol/providers/providers.go
Craig Peterson 3a90435357 Create a dynamic provider features matrix (#201)
* adding simple provider feature matrix generator

* filling out matrix

* clean output

* dead code

* explanatory text

* explanatory text

* typo

* move stuff around

* clean

* editing
2017-09-14 16:13:17 -04:00

144 lines
5.1 KiB
Go

package providers
import (
"encoding/json"
"fmt"
"log"
"github.com/StackExchange/dnscontrol/models"
)
//Registrar is an interface for a domain registrar. It can return a list of needed corrections to be applied in the future.
type Registrar interface {
GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Correction, error)
}
//DNSServiceProvider is able to generate a set of corrections that need to be made to correct records for a domain
type DNSServiceProvider interface {
GetNameservers(domain string) ([]*models.Nameserver, error)
GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error)
}
//DomainCreator should be implemented by providers that have the ability to add domains to an account. the create-domains command
//can be run to ensure all domains are present before running preview/push
type DomainCreator interface {
EnsureDomainExists(domain string) error
}
//RegistrarInitializer is a function to create a registrar. Function will be passed the unprocessed json payload from the configuration file for the given provider.
type RegistrarInitializer func(map[string]string) (Registrar, error)
var RegistrarTypes = map[string]RegistrarInitializer{}
//DspInitializer is a function to create a DNS service provider. Function will be passed the unprocessed json payload from the configuration file for the given provider.
type DspInitializer func(map[string]string, json.RawMessage) (DNSServiceProvider, error)
var DNSProviderTypes = map[string]DspInitializer{}
//RegisterRegistrarType adds a registrar type to the registry by providing a suitable initialization function.
func RegisterRegistrarType(name string, init RegistrarInitializer, pm ...ProviderMetadata) {
if _, ok := RegistrarTypes[name]; ok {
log.Fatalf("Cannot register registrar type %s multiple times", name)
}
RegistrarTypes[name] = init
unwrapProviderCapabilities(name, pm)
}
//RegisterDomainServiceProviderType adds a dsp to the registry with the given initialization function.
func RegisterDomainServiceProviderType(name string, init DspInitializer, pm ...ProviderMetadata) {
if _, ok := DNSProviderTypes[name]; ok {
log.Fatalf("Cannot register registrar type %s multiple times", name)
}
DNSProviderTypes[name] = init
unwrapProviderCapabilities(name, pm)
}
func createRegistrar(rType string, config map[string]string) (Registrar, error) {
initer, ok := RegistrarTypes[rType]
if !ok {
return nil, fmt.Errorf("Registrar type %s not declared.", rType)
}
return initer(config)
}
func CreateDNSProvider(dType string, config map[string]string, meta json.RawMessage) (DNSServiceProvider, error) {
initer, ok := DNSProviderTypes[dType]
if !ok {
return nil, fmt.Errorf("DSP type %s not declared", dType)
}
return initer(config, meta)
}
//CreateRegistrars will load all registrars from the dns config, and create instances of the correct type using data from
//the provider config to load relevant keys and options.
func CreateRegistrars(d *models.DNSConfig, providerConfigs map[string]map[string]string) (map[string]Registrar, error) {
regs := map[string]Registrar{}
for _, reg := range d.Registrars {
rawMsg, ok := providerConfigs[reg.Name]
if !ok && reg.Type != "NONE" {
return nil, fmt.Errorf("Registrar %s not listed in creds.json file.", reg.Name)
}
registrar, err := createRegistrar(reg.Type, rawMsg)
if err != nil {
return nil, err
}
regs[reg.Name] = registrar
}
return regs, nil
}
func CreateDsps(d *models.DNSConfig, providerConfigs map[string]map[string]string) (map[string]DNSServiceProvider, error) {
dsps := map[string]DNSServiceProvider{}
for _, dsp := range d.DNSProviders {
vals := providerConfigs[dsp.Name]
provider, err := CreateDNSProvider(dsp.Type, vals, dsp.Metadata)
if err != nil {
return nil, err
}
dsps[dsp.Name] = provider
}
return dsps, nil
}
// None is a basic provider type that does absolutely nothing. Can be useful as a placeholder for third parties or unimplemented providers.
type None struct{}
func (n None) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
return nil, nil
}
func (n None) GetNameservers(string) ([]*models.Nameserver, error) {
return nil, nil
}
func (n None) GetDomainCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
return nil, nil
}
func init() {
RegisterRegistrarType("NONE", func(map[string]string) (Registrar, error) {
return None{}, nil
})
}
type CustomRType struct {
Name string
Provider string
RealType string
}
// RegisterCustomRecordType registers a record type that is only valid for one provider.
// provider is the registered type of provider this is valid with
// name is the record type as it will appear in the js. (should be something like $PROVIDER_FOO)
// realType is the record type it will be replaced with after validation
func RegisterCustomRecordType(name, provider, realType string) {
customRecordTypes[name] = &CustomRType{Name: name, Provider: provider, RealType: realType}
}
// GetCustomRecordType returns a registered custom record type, or nil if none
func GetCustomRecordType(rType string) *CustomRType {
return customRecordTypes[rType]
}
var customRecordTypes = map[string]*CustomRType{}