mirror of
https://github.com/vxcontrol/external-dns.git
synced 2026-07-20 21:58:23 -04:00
Generated
+5
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"ImportPath": "github.com/rancher/external-dns",
|
||||
"GoVersion": "go1.4",
|
||||
"GoVersion": "go1.5.1",
|
||||
"Deps": [
|
||||
{
|
||||
"ImportPath": "github.com/Sirupsen/logrus",
|
||||
@@ -39,6 +39,10 @@
|
||||
{
|
||||
"ImportPath": "github.com/vaughan0/go-ini",
|
||||
"Rev": "a98ad7ee00ec53921f08832bc06ecf7fd600e6a1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/weppos/go-dnsimple/dnsimple",
|
||||
"Rev": "c82ccf106204c401644a24e8b45d16cf81e9cccb"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Scott Barron
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
package dnsimple
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ContactsService handles communication with the contact related
|
||||
// methods of the DNSimple API.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/contacts/
|
||||
type ContactsService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
type Contact struct {
|
||||
Id int `json:"id,omitempty"`
|
||||
Label string `json:"label,omitempty"`
|
||||
FirstName string `json:"first_name,omitempty"`
|
||||
LastName string `json:"last_name,omitempty"`
|
||||
JobTitle string `json:"job_title,omitempty"`
|
||||
Organization string `json:"organization_name,omitempty"`
|
||||
Email string `json:"email_address,omitempty"`
|
||||
Phone string `json:"phone,omitempty"`
|
||||
Fax string `json:"fax,omitempty"`
|
||||
Address1 string `json:"address1,omitempty"`
|
||||
Address2 string `json:"address2,omitempty"`
|
||||
City string `json:"city,omitempty"`
|
||||
Zip string `json:"postal_code,omitempty"`
|
||||
Country string `json:"country,omitempty"`
|
||||
CreatedAt *time.Time `json:"created_at,omitempty"`
|
||||
UpdatedAt *time.Time `json:"updated_at,omitempty"`
|
||||
}
|
||||
|
||||
type contactWrapper struct {
|
||||
Contact Contact `json:"contact"`
|
||||
}
|
||||
|
||||
// contactPath generates the resource path for given contact.
|
||||
func contactPath(contact interface{}) string {
|
||||
if contact != nil {
|
||||
return fmt.Sprintf("contacts/%d", contact)
|
||||
}
|
||||
return "contacts"
|
||||
}
|
||||
|
||||
// List the contacts.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/contacts/#list
|
||||
func (s *ContactsService) List() ([]Contact, *Response, error) {
|
||||
path := contactPath(nil)
|
||||
wrappedContacts := []contactWrapper{}
|
||||
|
||||
res, err := s.client.get(path, &wrappedContacts)
|
||||
if err != nil {
|
||||
return []Contact{}, res, err
|
||||
}
|
||||
|
||||
contacts := []Contact{}
|
||||
for _, contact := range wrappedContacts {
|
||||
contacts = append(contacts, contact.Contact)
|
||||
}
|
||||
|
||||
return contacts, res, nil
|
||||
}
|
||||
|
||||
// Create a new contact.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/contacts/#create
|
||||
func (s *ContactsService) Create(contactAttributes Contact) (Contact, *Response, error) {
|
||||
path := contactPath(nil)
|
||||
wrappedContact := contactWrapper{Contact: contactAttributes}
|
||||
returnedContact := contactWrapper{}
|
||||
|
||||
res, err := s.client.post(path, wrappedContact, &returnedContact)
|
||||
if err != nil {
|
||||
return Contact{}, res, err
|
||||
}
|
||||
|
||||
return returnedContact.Contact, res, nil
|
||||
}
|
||||
|
||||
// Get fetches a contact.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/contacts/#get
|
||||
func (s *ContactsService) Get(contactID int) (Contact, *Response, error) {
|
||||
path := contactPath(contactID)
|
||||
wrappedContact := contactWrapper{}
|
||||
|
||||
res, err := s.client.get(path, &wrappedContact)
|
||||
if err != nil {
|
||||
return Contact{}, res, err
|
||||
}
|
||||
|
||||
return wrappedContact.Contact, res, nil
|
||||
}
|
||||
|
||||
// Update a contact.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/contacts/#update
|
||||
func (s *ContactsService) Update(contactID int, contactAttributes Contact) (Contact, *Response, error) {
|
||||
path := contactPath(contactID)
|
||||
wrappedContact := contactWrapper{Contact: contactAttributes}
|
||||
returnedContact := contactWrapper{}
|
||||
|
||||
res, err := s.client.put(path, wrappedContact, &returnedContact)
|
||||
if err != nil {
|
||||
return Contact{}, res, err
|
||||
}
|
||||
|
||||
return returnedContact.Contact, res, nil
|
||||
}
|
||||
|
||||
// Delete a contact.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/contacts/#delete
|
||||
func (s *ContactsService) Delete(contactID int) (*Response, error) {
|
||||
path := contactPath(contactID)
|
||||
|
||||
return s.client.delete(path, nil)
|
||||
}
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
// Package dnsimple implements a client for the DNSimple API.
|
||||
//
|
||||
// In order to use this package you will need a DNSimple account and your API Token.
|
||||
package dnsimple
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
libraryVersion = "0.1"
|
||||
baseURL = "https://api.dnsimple.com/"
|
||||
userAgent = "dnsimple-go/" + libraryVersion
|
||||
|
||||
apiVersion = "v1"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
// HTTP client used to communicate with the API.
|
||||
HttpClient *http.Client
|
||||
|
||||
// API Token for the DNSimple account you want to use.
|
||||
ApiToken string
|
||||
|
||||
// Email associated with the provided DNSimple API Token.
|
||||
Email string
|
||||
|
||||
// Domain Token to be used for authentication
|
||||
// as an alternative to the DNSimple API Token for some domain-scoped operations.
|
||||
DomainToken string
|
||||
|
||||
// Base URL for API requests.
|
||||
// Defaults to the public DNSimple API, but can be set to a different endpoint (e.g. the sandbox).
|
||||
// BaseURL should always be specified with a trailing slash.
|
||||
BaseURL string
|
||||
|
||||
// User agent used when communicating with the DNSimple API.
|
||||
UserAgent string
|
||||
|
||||
// Services used for talking to different parts of the DNSimple API.
|
||||
Contacts *ContactsService
|
||||
Domains *DomainsService
|
||||
Registrar *RegistrarService
|
||||
Users *UsersService
|
||||
}
|
||||
|
||||
// NewClient returns a new DNSimple API client.
|
||||
func NewClient(apiToken, email string) *Client {
|
||||
c := &Client{ApiToken: apiToken, Email: email, HttpClient: &http.Client{}, BaseURL: baseURL, UserAgent: userAgent}
|
||||
c.Contacts = &ContactsService{client: c}
|
||||
c.Domains = &DomainsService{client: c}
|
||||
c.Registrar = &RegistrarService{client: c}
|
||||
c.Users = &UsersService{client: c}
|
||||
return c
|
||||
}
|
||||
|
||||
// NewRequest creates an API request.
|
||||
// The path is expected to be a relative path and will be resolved
|
||||
// according to the BaseURL of the Client. Paths should always be specified without a preceding slash.
|
||||
func (client *Client) NewRequest(method, path string, payload interface{}) (*http.Request, error) {
|
||||
url := client.BaseURL + fmt.Sprintf("%s/%s", apiVersion, path)
|
||||
|
||||
body := new(bytes.Buffer)
|
||||
if payload != nil {
|
||||
err := json.NewEncoder(body).Encode(payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(method, url, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Add("Accept", "application/json")
|
||||
req.Header.Add("User-Agent", client.UserAgent)
|
||||
req.Header.Add("X-DNSimple-Token", fmt.Sprintf("%s:%s", client.Email, client.ApiToken))
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (c *Client) get(path string, v interface{}) (*Response, error) {
|
||||
return c.Do("GET", path, nil, v)
|
||||
}
|
||||
|
||||
func (c *Client) post(path string, payload, v interface{}) (*Response, error) {
|
||||
return c.Do("POST", path, payload, v)
|
||||
}
|
||||
|
||||
func (c *Client) put(path string, payload, v interface{}) (*Response, error) {
|
||||
return c.Do("PUT", path, payload, v)
|
||||
}
|
||||
|
||||
func (c *Client) delete(path string, payload interface{}) (*Response, error) {
|
||||
return c.Do("DELETE", path, payload, nil)
|
||||
}
|
||||
|
||||
// Do sends an API request and returns the API response.
|
||||
// The API response is JSON decoded and stored in the value pointed by v,
|
||||
// or returned as an error if an API error has occurred.
|
||||
// If v implements the io.Writer interface, the raw response body will be written to v,
|
||||
// without attempting to decode it.
|
||||
func (c *Client) Do(method, path string, payload, v interface{}) (*Response, error) {
|
||||
req, err := c.NewRequest(method, path, payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := c.HttpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
response := &Response{Response: res}
|
||||
|
||||
err = CheckResponse(res)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
if v != nil {
|
||||
if w, ok := v.(io.Writer); ok {
|
||||
io.Copy(w, res.Body)
|
||||
} else {
|
||||
err = json.NewDecoder(res.Body).Decode(v)
|
||||
}
|
||||
}
|
||||
|
||||
return response, err
|
||||
}
|
||||
|
||||
// A Response represents an API response.
|
||||
type Response struct {
|
||||
*http.Response
|
||||
}
|
||||
|
||||
// An ErrorResponse represents an error caused by an API request.
|
||||
type ErrorResponse struct {
|
||||
Response *http.Response // HTTP response that caused this error
|
||||
Message string `json:"message"` // human-readable message
|
||||
}
|
||||
|
||||
// Error implements the error interface.
|
||||
func (r *ErrorResponse) Error() string {
|
||||
return fmt.Sprintf("%v %v: %d %v",
|
||||
r.Response.Request.Method, r.Response.Request.URL,
|
||||
r.Response.StatusCode, r.Message)
|
||||
}
|
||||
|
||||
// CheckResponse checks the API response for errors, and returns them if present.
|
||||
// A response is considered an error if the status code is different than 2xx. Specific requests
|
||||
// may have additional requirements, but this is sufficient in most of the cases.
|
||||
func CheckResponse(r *http.Response) error {
|
||||
if code := r.StatusCode; 200 <= code && code <= 299 {
|
||||
return nil
|
||||
}
|
||||
|
||||
errorResponse := &ErrorResponse{Response: r}
|
||||
err := json.NewDecoder(r.Body).Decode(errorResponse)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return errorResponse
|
||||
}
|
||||
|
||||
// Date custom type.
|
||||
type Date struct {
|
||||
time.Time
|
||||
}
|
||||
|
||||
// UnmarshalJSON handles the deserialization of the custom Date type.
|
||||
func (d *Date) UnmarshalJSON(data []byte) error {
|
||||
var s string
|
||||
if err := json.Unmarshal(data, &s); err != nil {
|
||||
return fmt.Errorf("date should be a string, got %s", data)
|
||||
}
|
||||
t, err := time.Parse("2006-01-02", s)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid date: %v", err)
|
||||
}
|
||||
d.Time = t
|
||||
return nil
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
package dnsimple
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DomainsService handles communication with the domain related
|
||||
// methods of the DNSimple API.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/domains/
|
||||
type DomainsService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
type Domain struct {
|
||||
Id int `json:"id,omitempty"`
|
||||
UserId int `json:"user_id,omitempty"`
|
||||
RegistrantId int `json:"registrant_id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
UnicodeName string `json:"unicode_name,omitempty"`
|
||||
Token string `json:"token,omitempty"`
|
||||
State string `json:"state,omitempty"`
|
||||
Language string `json:"language,omitempty"`
|
||||
Lockable bool `json:"lockable,omitempty"`
|
||||
AutoRenew bool `json:"auto_renew,omitempty"`
|
||||
WhoisProtected bool `json:"whois_protected,omitempty"`
|
||||
RecordCount int `json:"record_count,omitempty"`
|
||||
ServiceCount int `json:"service_count,omitempty"`
|
||||
ExpiresOn *Date `json:"expires_on,omitempty"`
|
||||
CreatedAt *time.Time `json:"created_at,omitempty"`
|
||||
UpdatedAt *time.Time `json:"updated_at,omitempty"`
|
||||
}
|
||||
|
||||
type domainWrapper struct {
|
||||
Domain Domain `json:"domain"`
|
||||
}
|
||||
|
||||
// domainRequest represents a generic wrapper for a domain request,
|
||||
// when domainWrapper cannot be used because of type constraint on Domain.
|
||||
type domainRequest struct {
|
||||
Domain interface{} `json:"domain"`
|
||||
}
|
||||
|
||||
func domainIdentifier(value interface{}) string {
|
||||
switch value := value.(type) {
|
||||
case string:
|
||||
return value
|
||||
case int:
|
||||
return fmt.Sprintf("%d", value)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// domainPath generates the resource path for given domain.
|
||||
func domainPath(domain interface{}) string {
|
||||
if domain != nil {
|
||||
return fmt.Sprintf("domains/%s", domainIdentifier(domain))
|
||||
}
|
||||
return "domains"
|
||||
}
|
||||
|
||||
// List the domains.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/domains/#list
|
||||
func (s *DomainsService) List() ([]Domain, *Response, error) {
|
||||
path := domainPath(nil)
|
||||
returnedDomains := []domainWrapper{}
|
||||
|
||||
res, err := s.client.get(path, &returnedDomains)
|
||||
if err != nil {
|
||||
return []Domain{}, res, err
|
||||
}
|
||||
|
||||
domains := []Domain{}
|
||||
for _, domain := range returnedDomains {
|
||||
domains = append(domains, domain.Domain)
|
||||
}
|
||||
|
||||
return domains, res, nil
|
||||
}
|
||||
|
||||
// Create a new domain.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/domains/#create
|
||||
func (s *DomainsService) Create(domainAttributes Domain) (Domain, *Response, error) {
|
||||
path := domainPath(nil)
|
||||
wrappedDomain := domainWrapper{Domain: domainAttributes}
|
||||
returnedDomain := domainWrapper{}
|
||||
|
||||
res, err := s.client.post(path, wrappedDomain, &returnedDomain)
|
||||
if err != nil {
|
||||
return Domain{}, res, err
|
||||
}
|
||||
|
||||
return returnedDomain.Domain, res, nil
|
||||
}
|
||||
|
||||
// Get fetches a domain.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/domains/#get
|
||||
func (s *DomainsService) Get(domain interface{}) (Domain, *Response, error) {
|
||||
path := domainPath(domain)
|
||||
returnedDomain := domainWrapper{}
|
||||
|
||||
res, err := s.client.get(path, &returnedDomain)
|
||||
if err != nil {
|
||||
return Domain{}, res, err
|
||||
}
|
||||
|
||||
return returnedDomain.Domain, res, nil
|
||||
}
|
||||
|
||||
// Delete a domain.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/domains/#delete
|
||||
func (s *DomainsService) Delete(domain interface{}) (*Response, error) {
|
||||
path := domainPath(domain)
|
||||
|
||||
return s.client.delete(path, nil)
|
||||
}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
package dnsimple
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Record struct {
|
||||
Id int `json:"id,omitempty"`
|
||||
DomainId int `json:"domain_id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Content string `json:"content,omitempty"`
|
||||
TTL int `json:"ttl,omitempty"`
|
||||
Priority int `json:"prio,omitempty"`
|
||||
Type string `json:"record_type,omitempty"`
|
||||
CreatedAt *time.Time `json:"created_at,omitempty"`
|
||||
UpdatedAt *time.Time `json:"updated_at,omitempty"`
|
||||
}
|
||||
|
||||
type recordWrapper struct {
|
||||
Record Record `json:"record"`
|
||||
}
|
||||
|
||||
// recordPath generates the resource path for given record that belongs to a domain.
|
||||
func recordPath(domain interface{}, record interface{}) string {
|
||||
path := fmt.Sprintf("domains/%s/records", domainIdentifier(domain))
|
||||
|
||||
if record != nil {
|
||||
path += fmt.Sprintf("/%d", record)
|
||||
}
|
||||
|
||||
return path
|
||||
}
|
||||
|
||||
// List the domain records.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/domains/records/#list
|
||||
func (s *DomainsService) ListRecords(domain interface{}, recordName, recordType string) ([]Record, *Response, error) {
|
||||
reqStr := recordPath(domain, nil)
|
||||
v := url.Values{}
|
||||
|
||||
if recordName != "" {
|
||||
v.Add("name", recordName)
|
||||
}
|
||||
if recordType != "" {
|
||||
v.Add("type", recordType)
|
||||
}
|
||||
reqStr += "?" + v.Encode()
|
||||
|
||||
wrappedRecords := []recordWrapper{}
|
||||
|
||||
res, err := s.client.get(reqStr, &wrappedRecords)
|
||||
if err != nil {
|
||||
return []Record{}, res, err
|
||||
}
|
||||
|
||||
records := []Record{}
|
||||
for _, record := range wrappedRecords {
|
||||
records = append(records, record.Record)
|
||||
}
|
||||
|
||||
return records, res, nil
|
||||
}
|
||||
|
||||
// CreateRecord creates a domain record.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/domains/records/#create
|
||||
func (s *DomainsService) CreateRecord(domain interface{}, recordAttributes Record) (Record, *Response, error) {
|
||||
path := recordPath(domain, nil)
|
||||
wrappedRecord := recordWrapper{Record: recordAttributes}
|
||||
returnedRecord := recordWrapper{}
|
||||
|
||||
res, err := s.client.post(path, wrappedRecord, &returnedRecord)
|
||||
if err != nil {
|
||||
return Record{}, res, err
|
||||
}
|
||||
|
||||
return returnedRecord.Record, res, nil
|
||||
}
|
||||
|
||||
// GetRecord fetches the domain record.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/domains/records/#get
|
||||
func (s *DomainsService) GetRecord(domain interface{}, recordID int) (Record, *Response, error) {
|
||||
path := recordPath(domain, recordID)
|
||||
wrappedRecord := recordWrapper{}
|
||||
|
||||
res, err := s.client.get(path, &wrappedRecord)
|
||||
if err != nil {
|
||||
return Record{}, res, err
|
||||
}
|
||||
|
||||
return wrappedRecord.Record, res, nil
|
||||
}
|
||||
|
||||
// UpdateRecord updates a domain record.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/domains/records/#update
|
||||
func (s *DomainsService) UpdateRecord(domain interface{}, recordID int, recordAttributes Record) (Record, *Response, error) {
|
||||
path := recordPath(domain, recordID)
|
||||
// name, content, ttl, priority
|
||||
wrappedRecord := recordWrapper{
|
||||
Record: Record{
|
||||
Name: recordAttributes.Name,
|
||||
Content: recordAttributes.Content,
|
||||
TTL: recordAttributes.TTL,
|
||||
Priority: recordAttributes.Priority}}
|
||||
returnedRecord := recordWrapper{}
|
||||
|
||||
res, err := s.client.put(path, wrappedRecord, &returnedRecord)
|
||||
if err != nil {
|
||||
return Record{}, res, err
|
||||
}
|
||||
|
||||
return returnedRecord.Record, res, nil
|
||||
}
|
||||
|
||||
// DeleteRecord deletes a domain record.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/domains/records/#delete
|
||||
func (s *DomainsService) DeleteRecord(domain interface{}, recordID int) (*Response, error) {
|
||||
path := recordPath(domain, recordID)
|
||||
|
||||
return s.client.delete(path, nil)
|
||||
}
|
||||
|
||||
// UpdateIP updates the IP of specific A record.
|
||||
//
|
||||
// This is not part of the standard API. However,
|
||||
// this is useful for Dynamic DNS (DDNS or DynDNS).
|
||||
func (record *Record) UpdateIP(client *Client, IP string) error {
|
||||
newRecord := Record{Content: IP, Name: record.Name}
|
||||
_, _, err := client.Domains.UpdateRecord(record.DomainId, record.Id, newRecord)
|
||||
return err
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package dnsimple
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type zoneResponse struct {
|
||||
Zone string `json:"zone,omitempty"`
|
||||
}
|
||||
|
||||
// GetZone downloads the Bind-like zone file.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/domains/zones/#get
|
||||
func (s *DomainsService) GetZone(domain interface{}) (string, *Response, error) {
|
||||
path := fmt.Sprintf("%s/zone", domainPath(domain))
|
||||
zoneResponse := zoneResponse{}
|
||||
|
||||
res, err := s.client.get(path, &zoneResponse)
|
||||
if err != nil {
|
||||
return "", res, err
|
||||
}
|
||||
|
||||
return zoneResponse.Zone, res, nil
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
package dnsimple
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// RegistrarService handles communication with the registrar related
|
||||
// methods of the DNSimple API.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/registrar/
|
||||
type RegistrarService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// ExtendedAttributes maps the additional attributes required by some registries.
|
||||
type ExtendedAttributes map[string]string
|
||||
|
||||
// ExtendedAttributes represents the transfer information.
|
||||
type TransferOrder struct {
|
||||
AuthCode string `json:"authinfo,omitempty"`
|
||||
}
|
||||
|
||||
// registrationRequest represents the body of a register or transfer request.
|
||||
type registrationRequest struct {
|
||||
Domain Domain `json:"domain"`
|
||||
ExtendedAttributes *ExtendedAttributes `json:"extended_attribute,omitempty"`
|
||||
TransferOrder *TransferOrder `json:"transfer_order,omitempty"`
|
||||
}
|
||||
|
||||
// IsAvailable checks if the domain is available or registered.
|
||||
//
|
||||
// See: http://developer.dnsimple.com/registrar/#check
|
||||
func (s *RegistrarService) IsAvailable(domain string) (bool, error) {
|
||||
path := fmt.Sprintf("%s/check", domainPath(domain))
|
||||
|
||||
res, err := s.client.get(path, nil)
|
||||
if err != nil && res != nil && res.StatusCode != 404 {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return res.StatusCode == 404, nil
|
||||
}
|
||||
|
||||
// Register a domain.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/registrar/#register
|
||||
func (s *RegistrarService) Register(domain string, registrantID int, extendedAttributes *ExtendedAttributes) (Domain, *Response, error) {
|
||||
request := registrationRequest{
|
||||
Domain: Domain{Name: domain, RegistrantId: registrantID},
|
||||
ExtendedAttributes: extendedAttributes,
|
||||
}
|
||||
returnedDomain := domainWrapper{}
|
||||
|
||||
res, err := s.client.post("domain_registrations", request, &returnedDomain)
|
||||
if err != nil {
|
||||
return Domain{}, res, err
|
||||
}
|
||||
|
||||
return returnedDomain.Domain, res, nil
|
||||
}
|
||||
|
||||
// Transfer a domain.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/registrar/#transfer
|
||||
func (s *RegistrarService) Transfer(domain string, registrantID int, authCode string, extendedAttributes *ExtendedAttributes) (Domain, *Response, error) {
|
||||
request := registrationRequest{
|
||||
Domain: Domain{Name: domain, RegistrantId: registrantID},
|
||||
ExtendedAttributes: extendedAttributes,
|
||||
TransferOrder: &TransferOrder{AuthCode: authCode},
|
||||
}
|
||||
returnedDomain := domainWrapper{}
|
||||
|
||||
res, err := s.client.post("domain_transfers", request, &returnedDomain)
|
||||
if err != nil {
|
||||
return Domain{}, res, err
|
||||
}
|
||||
|
||||
return returnedDomain.Domain, res, nil
|
||||
}
|
||||
|
||||
// renewDomain represents the body of a Renew request.
|
||||
type renewDomain struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
RenewWhoisPrivacy bool `json:"renew_whois_privacy,omitempty"`
|
||||
}
|
||||
|
||||
// Renew the domain, optionally renewing WHOIS privacy service.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/registrar/#renew
|
||||
func (s *RegistrarService) Renew(domain string, renewWhoisPrivacy bool) (Domain, *Response, error) {
|
||||
request := domainRequest{Domain: renewDomain{
|
||||
Name: domain,
|
||||
RenewWhoisPrivacy: renewWhoisPrivacy,
|
||||
}}
|
||||
returnedDomain := domainWrapper{}
|
||||
|
||||
res, err := s.client.post("domain_renewals", request, &returnedDomain)
|
||||
if err != nil {
|
||||
return Domain{}, res, err
|
||||
}
|
||||
|
||||
return returnedDomain.Domain, res, nil
|
||||
}
|
||||
|
||||
// EnableAutoRenewal enables the auto-renewal feature for the domain.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/registrar/autorenewal/#enable
|
||||
func (s *RegistrarService) EnableAutoRenewal(domain interface{}) (*Response, error) {
|
||||
path := fmt.Sprintf("%s/auto_renewal", domainPath(domain))
|
||||
|
||||
res, err := s.client.post(path, nil, nil)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// DisableAutoRenewal disables the auto-renewal feature for the domain.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/registrar/autorenewal/#disable
|
||||
func (s *RegistrarService) DisableAutoRenewal(domain interface{}) (*Response, error) {
|
||||
path := fmt.Sprintf("%s/auto_renewal", domainPath(domain))
|
||||
|
||||
res, err := s.client.delete(path, nil)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package dnsimple
|
||||
|
||||
import ()
|
||||
|
||||
// UsersService handles communication with the uer related
|
||||
// methods of the DNSimple API.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/users/
|
||||
type UsersService struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// User represents a DNSimple user.
|
||||
type User struct {
|
||||
Id int `json:"id,omitempty"`
|
||||
Email string `json:"email,omitempty"`
|
||||
}
|
||||
|
||||
type userWrapper struct {
|
||||
User User `json:"user"`
|
||||
}
|
||||
|
||||
// User gets the logged in user.
|
||||
//
|
||||
// DNSimple API docs: http://developer.dnsimple.com/users/
|
||||
func (s *UsersService) User() (User, *Response, error) {
|
||||
wrappedUser := userWrapper{}
|
||||
|
||||
res, err := s.client.get("user", &wrappedUser)
|
||||
if err != nil {
|
||||
return User{}, res, err
|
||||
}
|
||||
|
||||
return wrappedUser.User, res, nil
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
package providers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/rancher/external-dns/dns"
|
||||
"github.com/weppos/go-dnsimple/dnsimple"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func init() {
|
||||
apiToken := os.Getenv("DNSIMPLE_TOKEN")
|
||||
if len(apiToken) == 0 {
|
||||
logrus.Info("DNSIMPLE_TOKEN is not set, skipping init of DNSimple provider")
|
||||
return
|
||||
}
|
||||
|
||||
email := os.Getenv("DNSIMPLE_EMAIL")
|
||||
if len(email) == 0 {
|
||||
logrus.Info("DNSIMPLE_EMAIL is not set, skipping init of DNSimple provider")
|
||||
return
|
||||
}
|
||||
|
||||
dnsimpleHandler := &DNSimpleHandler{}
|
||||
if err := RegisterProvider("dnsimple", dnsimpleHandler); err != nil {
|
||||
logrus.Fatal("Could not register dnsimple provider")
|
||||
}
|
||||
|
||||
dnsimpleHandler.root = strings.TrimSuffix(dns.RootDomainName, ".")
|
||||
dnsimpleHandler.client = dnsimple.NewClient(apiToken, email)
|
||||
|
||||
domains, _, err := dnsimpleHandler.client.Domains.List()
|
||||
if err != nil {
|
||||
logrus.Fatalf("Failed to list hosted zones: %v", err)
|
||||
}
|
||||
|
||||
found := false
|
||||
for _, domain := range domains {
|
||||
if domain.Name == dnsimpleHandler.root {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
logrus.Fatalf("Hosted zone %s is missing", dnsimpleHandler.root)
|
||||
}
|
||||
|
||||
logrus.Infof("Configured %s with hosted zone %q ", dnsimpleHandler.GetName(), dnsimpleHandler.root)
|
||||
}
|
||||
|
||||
type DNSimpleHandler struct {
|
||||
client *dnsimple.Client
|
||||
root string
|
||||
}
|
||||
|
||||
func (*DNSimpleHandler) GetName() string {
|
||||
return "DNSimple"
|
||||
}
|
||||
|
||||
func (d *DNSimpleHandler) parseName(record dns.DnsRecord) string {
|
||||
name := strings.TrimSuffix(record.Fqdn, fmt.Sprintf(".%s.", d.root))
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
func (d *DNSimpleHandler) AddRecord(record dns.DnsRecord) error {
|
||||
name := d.parseName(record)
|
||||
for _, rec := range record.Records {
|
||||
recordInput := dnsimple.Record{
|
||||
Name: name,
|
||||
TTL: record.TTL,
|
||||
Type: record.Type,
|
||||
Content: rec,
|
||||
}
|
||||
_, _, err := d.client.Domains.CreateRecord(d.root, recordInput)
|
||||
if err != nil {
|
||||
return fmt.Errorf("DNSimple API call has failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DNSimpleHandler) findRecords(record dns.DnsRecord) ([]dnsimple.Record, error) {
|
||||
var records []dnsimple.Record
|
||||
resp, _, err := d.client.Domains.ListRecords(d.root, "", "")
|
||||
if err != nil {
|
||||
return records, fmt.Errorf("DNSimple API call has failed: %v", err)
|
||||
}
|
||||
|
||||
name := d.parseName(record)
|
||||
for _, rec := range resp {
|
||||
if rec.Name == name && rec.Type == record.Type {
|
||||
records = append(records, rec)
|
||||
}
|
||||
}
|
||||
|
||||
return records, nil
|
||||
}
|
||||
|
||||
func (d *DNSimpleHandler) UpdateRecord(record dns.DnsRecord) error {
|
||||
err := d.RemoveRecord(record)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return d.AddRecord(record)
|
||||
}
|
||||
|
||||
func (d *DNSimpleHandler) RemoveRecord(record dns.DnsRecord) error {
|
||||
records, err := d.findRecords(record)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, rec := range records {
|
||||
_, err := d.client.Domains.DeleteRecord(d.root, rec.Id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("DNSimple API call has failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DNSimpleHandler) GetRecords() ([]dns.DnsRecord, error) {
|
||||
var records []dns.DnsRecord
|
||||
|
||||
recordResp, _, err := d.client.Domains.ListRecords(d.root, "", "")
|
||||
if err != nil {
|
||||
return records, fmt.Errorf("DNSimple API call has failed: %v", err)
|
||||
}
|
||||
|
||||
recordMap := map[string]map[string][]string{}
|
||||
recordTTLs := map[string]map[string]int{}
|
||||
|
||||
for _, rec := range recordResp {
|
||||
var fqdn string
|
||||
if rec.Name == "" {
|
||||
fqdn = dns.RootDomainName
|
||||
} else {
|
||||
fqdn = fmt.Sprintf("%s.%s", rec.Name, dns.RootDomainName)
|
||||
}
|
||||
|
||||
recordTTLs[fqdn] = map[string]int{}
|
||||
recordTTLs[fqdn][rec.Type] = rec.TTL
|
||||
recordSet, exists := recordMap[fqdn]
|
||||
if exists {
|
||||
recordSlice, sliceExists := recordSet[rec.Type]
|
||||
if sliceExists {
|
||||
recordSlice = append(recordSlice, rec.Content)
|
||||
} else {
|
||||
recordSet[rec.Type] = []string{rec.Content}
|
||||
}
|
||||
} else {
|
||||
recordMap[fqdn] = map[string][]string{}
|
||||
recordMap[fqdn][rec.Type] = []string{rec.Content}
|
||||
}
|
||||
}
|
||||
|
||||
for fqdn, recordSet := range recordMap {
|
||||
for recordType, recordSlice := range recordSet {
|
||||
ttl := recordTTLs[fqdn][recordType]
|
||||
record := dns.DnsRecord{Fqdn: fqdn, Records: recordSlice, Type: recordType, TTL: ttl}
|
||||
records = append(records, record)
|
||||
}
|
||||
}
|
||||
return records, nil
|
||||
}
|
||||
+15
-4
@@ -21,6 +21,21 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
if len(os.Getenv("AWS_REGION")) == 0 {
|
||||
logrus.Info("AWS_REGION is not set, skipping init of Route53 provider")
|
||||
return
|
||||
}
|
||||
|
||||
if len(os.Getenv("AWS_ACCESS_KEY")) == 0 {
|
||||
logrus.Info("AWS_ACCESS_KEY is not set, skipping init of Route53 provider")
|
||||
return
|
||||
}
|
||||
|
||||
if len(os.Getenv("AWS_SECRET_KEY")) == 0 {
|
||||
logrus.Info("AWS_SECRET_KEY is not set, skipping init of Route53 provider")
|
||||
return
|
||||
}
|
||||
|
||||
route53Handler := &Route53Handler{}
|
||||
if err := RegisterProvider("route53", route53Handler); err != nil {
|
||||
logrus.Fatal("Could not register route53 provider")
|
||||
@@ -40,10 +55,6 @@ func init() {
|
||||
func setRegion() error {
|
||||
|
||||
regionName := os.Getenv("AWS_REGION")
|
||||
if len(regionName) == 0 {
|
||||
return fmt.Errorf("AWS_REGION is not set")
|
||||
}
|
||||
|
||||
r, ok := aws.Regions[regionName]
|
||||
if !ok {
|
||||
return fmt.Errorf("Could not find region by name %s", regionName)
|
||||
|
||||
Reference in New Issue
Block a user