github.com/teknogeek/dnscontrol/v2@v2.10.1-0.20200227202244-ae299b55ba42/providers/opensrs/opensrsProvider.go (about)

     1  package opensrs
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"sort"
     8  	"strings"
     9  
    10  	"github.com/StackExchange/dnscontrol/v2/models"
    11  	"github.com/StackExchange/dnscontrol/v2/providers"
    12  
    13  	opensrs "github.com/philhug/opensrs-go/opensrs"
    14  )
    15  
    16  var docNotes = providers.DocumentationNotes{
    17  	providers.DocCreateDomains:       providers.Cannot(),
    18  	providers.DocOfficiallySupported: providers.Cannot(),
    19  	providers.CanUseTLSA:             providers.Cannot(),
    20  	providers.CanGetZones:            providers.Unimplemented(),
    21  }
    22  
    23  func init() {
    24  	providers.RegisterRegistrarType("OPENSRS", newReg)
    25  }
    26  
    27  var defaultNameServerNames = []string{
    28  	"ns1.systemdns.com",
    29  	"ns2.systemdns.com",
    30  	"ns3.systemdns.com",
    31  }
    32  
    33  type OpenSRSApi struct {
    34  	UserName string // reseller user name
    35  	ApiKey   string // API Key
    36  
    37  	BaseURL string          // An alternate base URI
    38  	client  *opensrs.Client // Client
    39  }
    40  
    41  func (c *OpenSRSApi) GetNameservers(domainName string) ([]*models.Nameserver, error) {
    42  	return models.StringsToNameservers(defaultNameServerNames), nil
    43  }
    44  
    45  func (c *OpenSRSApi) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
    46  	corrections := []*models.Correction{}
    47  
    48  	nameServers, err := c.getNameservers(dc.Name)
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  
    53  	sort.Strings(nameServers)
    54  	actual := strings.Join(nameServers, ",")
    55  
    56  	expectedSet := []string{}
    57  	for _, ns := range dc.Nameservers {
    58  		expectedSet = append(expectedSet, ns.Name)
    59  	}
    60  	sort.Strings(expectedSet)
    61  	expected := strings.Join(expectedSet, ",")
    62  
    63  	if actual != expected {
    64  		return []*models.Correction{
    65  			{
    66  				Msg: fmt.Sprintf("Update nameservers %s -> %s", actual, expected),
    67  				F:   c.updateNameserversFunc(expectedSet, dc.Name),
    68  			},
    69  		}, nil
    70  	}
    71  
    72  	return corrections, nil
    73  }
    74  
    75  // OpenSRS calls
    76  
    77  func (c *OpenSRSApi) getClient() *opensrs.Client {
    78  	return c.client
    79  }
    80  
    81  // Returns the name server names that should be used. If the domain is registered
    82  // then this method will return the delegation name servers. If this domain
    83  // is hosted only, then it will return the default OpenSRS name servers.
    84  func (c *OpenSRSApi) getNameservers(domainName string) ([]string, error) {
    85  	client := c.getClient()
    86  
    87  	status, err := client.Domains.GetDomain(domainName, "status", 1)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  
    92  	if status.Attributes.LockState == "0" {
    93  		dom, err := client.Domains.GetDomain(domainName, "nameservers", 1)
    94  		if err != nil {
    95  			return nil, err
    96  		}
    97  		return dom.Attributes.NameserverList.ToString(), nil
    98  	} else {
    99  		return nil, errors.New("Domain is locked")
   100  	}
   101  }
   102  
   103  // Returns a function that can be invoked to change the delegation of the domain to the given name server names.
   104  func (c *OpenSRSApi) updateNameserversFunc(nameServerNames []string, domainName string) func() error {
   105  	return func() error {
   106  		client := c.getClient()
   107  
   108  		_, err := client.Domains.UpdateDomainNameservers(domainName, nameServerNames)
   109  		if err != nil {
   110  			return err
   111  		}
   112  		return nil
   113  	}
   114  }
   115  
   116  // constructors
   117  
   118  func newReg(conf map[string]string) (providers.Registrar, error) {
   119  	return newProvider(conf, nil)
   120  }
   121  
   122  func newProvider(m map[string]string, metadata json.RawMessage) (*OpenSRSApi, error) {
   123  	api := &OpenSRSApi{}
   124  	api.ApiKey = m["apikey"]
   125  
   126  	if api.ApiKey == "" {
   127  		return nil, fmt.Errorf("OpenSRS apikey must be provided.")
   128  	}
   129  
   130  	api.UserName = m["username"]
   131  	if api.UserName == "" {
   132  		return nil, fmt.Errorf("OpenSRS username key must be provided.")
   133  	}
   134  
   135  	if m["baseurl"] != "" {
   136  		api.BaseURL = m["baseurl"]
   137  	}
   138  
   139  	api.client = opensrs.NewClient(opensrs.NewApiKeyMD5Credentials(api.UserName, api.ApiKey))
   140  	if api.BaseURL != "" {
   141  		api.client.BaseURL = api.BaseURL
   142  	}
   143  
   144  	return api, nil
   145  }