mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-01-11 01:47:53 +08:00
137 lines
3.2 KiB
Go
137 lines
3.2 KiB
Go
package dynadot
|
|
|
|
import (
|
|
"encoding/xml"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
)
|
|
|
|
// API layer for Dynadot
|
|
|
|
type dynadotProvider struct {
|
|
key string
|
|
}
|
|
|
|
type requestParams map[string]string
|
|
|
|
type header struct {
|
|
SuccessCode int `xml:"SuccessCode"`
|
|
Status string `xml:"Status"`
|
|
Error string `xml:"Error,omitempty"`
|
|
}
|
|
|
|
type addNsResponse struct {
|
|
XMLName xml.Name `xml:"AddNsResponse"`
|
|
AddNsHeader header `xml:"AddNsHeader"`
|
|
}
|
|
|
|
type setNsResponse struct {
|
|
XMLName xml.Name `xml:"SetNsResponse"`
|
|
SetNsHeader header `xml:"SetNsHeader"`
|
|
}
|
|
|
|
type getNsResponse struct {
|
|
XMLName xml.Name `xml:"GetNsResponse"`
|
|
NsContent nsContent `xml:"NsContent"`
|
|
GetNsHeader header `xml:"GetNsHeader"`
|
|
}
|
|
|
|
type nsContent struct {
|
|
Host []string `xml:"Host"`
|
|
NsName string `xml:"NsName"`
|
|
}
|
|
|
|
func (c *dynadotProvider) getNameservers(domain string) ([]string, error) {
|
|
bodyString, err := c.get("get_ns", requestParams{"domain": domain})
|
|
if err != nil {
|
|
return []string{}, fmt.Errorf("failed NS list (Dynadot): %w", err)
|
|
}
|
|
var ns getNsResponse
|
|
if err := xml.Unmarshal(bodyString, &ns); err != nil {
|
|
return []string{}, fmt.Errorf("failed to unmarshal NS list (Dynadot): %w", err)
|
|
}
|
|
|
|
if ns.GetNsHeader.SuccessCode != 0 {
|
|
return []string{}, fmt.Errorf("failed NS list (Dynadot): %s", ns.GetNsHeader.Error)
|
|
}
|
|
|
|
hosts := []string{}
|
|
hosts = append(hosts, ns.NsContent.Host...)
|
|
return hosts, nil
|
|
}
|
|
|
|
func (c *dynadotProvider) updateNameservers(ns []string, domain string) error {
|
|
if len(ns) > 13 {
|
|
return errors.New("failed NS update (Dynadot): only up to 13 nameservers are supported")
|
|
}
|
|
|
|
// Nameservers must first be added to the Dynadot account
|
|
for _, host := range ns {
|
|
b, err := c.get("add_ns", requestParams{"host": host})
|
|
if err != nil {
|
|
return fmt.Errorf("failed NS add (Dynadot): %w", err)
|
|
}
|
|
var resp addNsResponse
|
|
err = xml.Unmarshal(b, &resp)
|
|
if err != nil {
|
|
return fmt.Errorf("failed NS add (Dynadot): %w", err)
|
|
}
|
|
|
|
if resp.AddNsHeader.SuccessCode != 0 {
|
|
// No apparent way to get all existing entries on an account, so filter
|
|
if strings.Contains(resp.AddNsHeader.Error, "already exists") {
|
|
continue
|
|
}
|
|
return fmt.Errorf("failed NS add (Dynadot): %s", resp.AddNsHeader.Error)
|
|
}
|
|
}
|
|
|
|
rec := requestParams{}
|
|
rec["domain"] = domain
|
|
// supported prams: ns0 - ns12
|
|
for i, h := range ns {
|
|
rec[fmt.Sprintf("%s%d", "ns", i)] = h
|
|
}
|
|
|
|
b, err := c.get("set_ns", rec)
|
|
if err != nil {
|
|
return fmt.Errorf("failed NS set (Dynadot): %w", err)
|
|
}
|
|
|
|
var resp setNsResponse
|
|
err = xml.Unmarshal(b, &resp)
|
|
if err != nil {
|
|
return fmt.Errorf("failed NS add (Dynadot): %w", err)
|
|
}
|
|
|
|
if resp.SetNsHeader.SuccessCode != 0 {
|
|
return fmt.Errorf("failed NS add (Dynadot): %s", resp.SetNsHeader.Error)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *dynadotProvider) get(command string, params requestParams) ([]byte, error) {
|
|
client := &http.Client{}
|
|
req, _ := http.NewRequest(http.MethodGet, "https://api.dynadot.com/api3.xml", nil)
|
|
q := req.URL.Query()
|
|
|
|
q.Add("key", c.key)
|
|
q.Add("command", command)
|
|
|
|
for pName, pValue := range params {
|
|
q.Add(pName, pValue)
|
|
}
|
|
|
|
req.URL.RawQuery = q.Encode()
|
|
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return []byte{}, err
|
|
}
|
|
|
|
return io.ReadAll(resp.Body)
|
|
}
|