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