1
0
mirror of https://github.com/StackExchange/dnscontrol.git synced 2024-05-11 05:55:12 +00:00

vendor github.com/prasmussen/gandi-api with new LiveDNS support. (#302)

This commit is contained in:
Tom Limoncelli
2018-01-16 17:11:11 -05:00
committed by GitHub
parent 7b8d608019
commit 9764322d0e
2 changed files with 184 additions and 25 deletions

View File

@ -1,26 +1,50 @@
package client
import "github.com/kolo/xmlrpc"
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"strings"
const (
Production SystemType = iota
Testing
"github.com/kolo/xmlrpc"
)
const (
// Production is the SystemType to provide to New to use the production XML API
Production SystemType = iota
// Testing is the SystemType to provide to New to use the test XML API
Testing
// LiveDNS is the SystemType to provide to New to use the Live DNS REST API
// Full documentation of the API is available here: http://doc.livedns.gandi.net/
LiveDNS
)
// SystemType is the type used to resolve gandi API address
type SystemType int
func (self SystemType) Url() string {
if self == Production {
// Url returns the actual gandi API base URL
func (s SystemType) Url() string {
if s == Production {
return "https://rpc.gandi.net/xmlrpc/"
}
if s == LiveDNS {
return "https://dns.api.gandi.net/api/v5/"
}
return "https://rpc.ote.gandi.net/xmlrpc/"
}
// Client holds the configuration of a gandi client
type Client struct {
// Key is the API key to provide to gandi
Key string
// Url is the base URL of the gandi API
Url string
}
// New creates a new gandi client for the given system
func New(apiKey string, system SystemType) *Client {
return &Client{
Key: apiKey,
@ -28,10 +52,145 @@ func New(apiKey string, system SystemType) *Client {
}
}
func (self *Client) Call(serviceMethod string, args []interface{}, reply interface{}) error {
rpc, err := xmlrpc.NewClient(self.Url, nil)
// Call performs an acual XML RPC call to the gandi API
func (c *Client) Call(serviceMethod string, args []interface{}, reply interface{}) error {
rpc, err := xmlrpc.NewClient(c.Url, nil)
if err != nil {
return err
}
return rpc.Call(serviceMethod, args, reply)
}
// DoRest performs a request to gandi LiveDNS api and optionnally decodes the reply
func (c *Client) DoRest(req *http.Request, decoded interface{}) (*http.Response, error) {
if decoded != nil {
req.Header.Set("Accept", "application/json")
}
client := http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
if resp.StatusCode == http.StatusUnauthorized {
return nil, fmt.Errorf("the server returned unauthorized code. Your API key might be invalid or have expired")
}
//
defer func() { err = resp.Body.Close() }()
if decoded != nil {
b, e := ioutil.ReadAll(resp.Body)
if e != nil {
return nil, e
}
if len(b) > 0 {
e = json.Unmarshal(b, decoded)
if e != nil {
return nil, e
}
}
resp.Body = ioutil.NopCloser(bytes.NewReader(b))
}
return resp, err
}
// NewJSONRequest creates a new authenticated to gandi live DNS REST API.
// If data is not null, it will be encoded as json and prodived in the request body
func (c *Client) NewJSONRequest(method string, url string, data interface{}) (*http.Request, error) {
var reader io.Reader
if data != nil {
b, err := json.Marshal(data)
if err != nil {
return nil, err
}
reader = bytes.NewReader(b)
}
req, err := http.NewRequest(method, fmt.Sprintf("%s/%s", strings.TrimRight(c.Url, "/"), strings.TrimLeft(url, "/")), reader)
if err != nil {
return nil, err
}
if data != nil {
req.Header.Set("Content-Type", "application/json")
}
req.Header.Set("X-Api-Key", c.Key)
return req, nil
}
// Get performs a Get request to gandi Live DNS api and decodes the returned data if a not null decoded pointer is provided
func (c *Client) Get(URI string, decoded interface{}) (*http.Response, error) {
req, err := c.NewJSONRequest("GET", URI, nil)
if err != nil {
return nil, err
}
resp, err := c.DoRest(req, decoded)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("Unexpected http code %d on URL %v. expecting %d", resp.StatusCode, resp.Request.URL, http.StatusOK)
}
return resp, err
}
// Delete performs a Delete request to gandi Live DNS api and decodes the returned data if a not null decoded pointer is provided
func (c *Client) Delete(URI string, decoded interface{}) (*http.Response, error) {
req, err := c.NewJSONRequest("DELETE", URI, nil)
if err != nil {
return nil, err
}
resp, err := c.DoRest(req, decoded)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusNoContent {
return nil, fmt.Errorf("Unexpected http code %d on URL %v. expecting %d", resp.StatusCode, resp.Request.URL, http.StatusNoContent)
}
return resp, err
}
// Post performs a Post request request to gandi Live DNS api
// - with data encoded as JSON if a not null data pointer is provided
// - decodes the returned data if a not null decoded pointer is provided
// - ensures the status code is an HTTP accepted
func (c *Client) Post(URI string, data interface{}, decoded interface{}) (*http.Response, error) {
req, err := c.NewJSONRequest("POST", URI, data)
if err != nil {
return nil, err
}
resp, err := c.DoRest(req, decoded)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusCreated {
return nil, fmt.Errorf("Unexpected http code %d on URL %v. expecting %d", resp.StatusCode, resp.Request.URL, http.StatusCreated)
}
return resp, err
}
// Put performs a Put request to gandi Live DNS api
// - with data encoded as JSON if a not null data pointer is provided
// - decodes the returned data if a not null decoded pointer is provided
func (c *Client) Put(URI string, data interface{}, decoded interface{}) (*http.Response, error) {
req, err := c.NewJSONRequest("PUT", URI, data)
if err != nil {
return nil, err
}
return c.DoRest(req, decoded)
}
// Patch performs a Patch request to gandi Live DNS api
// - with data encoded as JSON if a not null data pointer is provided
// - decodes the returned data if a not null decoded pointer is provided
// - ensures the status code is an HTTP accepted
func (c *Client) Patch(URI string, data interface{}, decoded interface{}) (*http.Response, error) {
req, err := c.NewJSONRequest("PATCH", URI, data)
if err != nil {
return nil, err
}
resp, err := c.DoRest(req, decoded)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusAccepted {
return nil, fmt.Errorf("Unexpected http code %d on URL %v. expecting %d", resp.StatusCode, resp.Request.URL, http.StatusAccepted)
}
return resp, err
}