github.com/pmoroney/dnscontrol@v0.2.4-0.20171024134423-fad98f73f44a/providers/namedotcom/namedotcomProvider.go (about)

     1  //Package namedotcom implements a registrar that uses the name.com api to set name servers. It will self register it's providers when imported.
     2  package namedotcom
     3  
     4  import (
     5  	"bytes"
     6  	"encoding/json"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"net/http"
    10  
    11  	"github.com/StackExchange/dnscontrol/providers"
    12  )
    13  
    14  const defaultApiBase = "https://api.name.com/api"
    15  
    16  type nameDotCom struct {
    17  	APIUrl  string `json:"apiurl"`
    18  	APIUser string `json:"apiuser"`
    19  	APIKey  string `json:"apikey"`
    20  }
    21  
    22  var docNotes = providers.DocumentationNotes{
    23  	providers.DocDualHost:            providers.Cannot("Apex NS records not editable"),
    24  	providers.DocCreateDomains:       providers.Cannot("New domains require registration"),
    25  	providers.DocOfficiallySupported: providers.Can(),
    26  	providers.CanUsePTR:              providers.Cannot("PTR records are not supported (See Link)", "https://www.name.com/support/articles/205188508-Reverse-DNS-records"),
    27  }
    28  
    29  func newReg(conf map[string]string) (providers.Registrar, error) {
    30  	return newProvider(conf)
    31  }
    32  
    33  func newDsp(conf map[string]string, meta json.RawMessage) (providers.DNSServiceProvider, error) {
    34  	return newProvider(conf)
    35  }
    36  
    37  func newProvider(conf map[string]string) (*nameDotCom, error) {
    38  	api := &nameDotCom{}
    39  	api.APIUser, api.APIKey, api.APIUrl = conf["apiuser"], conf["apikey"], conf["apiurl"]
    40  	if api.APIKey == "" || api.APIUser == "" {
    41  		return nil, fmt.Errorf("Name.com apikey and apiuser must be provided.")
    42  	}
    43  	if api.APIUrl == "" {
    44  		api.APIUrl = defaultApiBase
    45  	}
    46  	return api, nil
    47  }
    48  
    49  func init() {
    50  	providers.RegisterRegistrarType("NAMEDOTCOM", newReg)
    51  	providers.RegisterDomainServiceProviderType("NAMEDOTCOM", newDsp, providers.CanUseAlias, providers.CanUseSRV, docNotes)
    52  }
    53  
    54  ///
    55  //various http helpers for interacting with api
    56  ///
    57  
    58  func (n *nameDotCom) addAuth(r *http.Request) {
    59  	r.Header.Add("Api-Username", n.APIUser)
    60  	r.Header.Add("Api-Token", n.APIKey)
    61  }
    62  
    63  type apiResult struct {
    64  	Result struct {
    65  		Code    int    `json:"code"`
    66  		Message string `json:"message"`
    67  	} `json:"result"`
    68  }
    69  
    70  func (r *apiResult) getErr() error {
    71  	if r == nil {
    72  		return nil
    73  	}
    74  	if r.Result.Code != 100 {
    75  		if r.Result.Message == "" {
    76  			return fmt.Errorf("Unknown error from name.com")
    77  		}
    78  		return fmt.Errorf(r.Result.Message)
    79  	}
    80  	return nil
    81  }
    82  
    83  //perform http GET and unmarshal response json into target struct
    84  func (n *nameDotCom) get(url string, target interface{}) error {
    85  	req, err := http.NewRequest("GET", url, nil)
    86  	if err != nil {
    87  		return err
    88  	}
    89  	n.addAuth(req)
    90  	resp, err := http.DefaultClient.Do(req)
    91  	if err != nil {
    92  		return err
    93  	}
    94  	defer resp.Body.Close()
    95  	data, err := ioutil.ReadAll(resp.Body)
    96  	if err != nil {
    97  		return err
    98  	}
    99  	return json.Unmarshal(data, target)
   100  }
   101  
   102  // perform http POST, json marshalling the given data into the body
   103  func (n *nameDotCom) post(url string, data interface{}) (*apiResult, error) {
   104  	buf := &bytes.Buffer{}
   105  	enc := json.NewEncoder(buf)
   106  	if err := enc.Encode(data); err != nil {
   107  		return nil, err
   108  	}
   109  	req, err := http.NewRequest("POST", url, buf)
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  	n.addAuth(req)
   114  	resp, err := http.DefaultClient.Do(req)
   115  	if err != nil {
   116  		return nil, err
   117  	}
   118  	defer resp.Body.Close()
   119  	text, err := ioutil.ReadAll(resp.Body)
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  	result := &apiResult{}
   124  	if err = json.Unmarshal(text, result); err != nil {
   125  		return nil, err
   126  	}
   127  	return result, nil
   128  }