New source: GoDaddy
continuous-integration/drone/push Build was killed Details

This commit is contained in:
nemunaire 2021-01-06 03:22:14 +01:00
parent eaf2f1d39a
commit a9f86307d5
6 changed files with 292 additions and 0 deletions

1
go.mod
View File

@ -8,6 +8,7 @@ require (
github.com/julienschmidt/httprouter v1.3.0
github.com/miekg/dns v1.1.29
github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014
github.com/oze4/godaddygo v1.3.17
github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/syndtr/goleveldb v1.0.0
github.com/yuin/goldmark v1.1.30

2
go.sum
View File

@ -25,6 +25,8 @@ github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014 h1:37VE5TYj2m/FLA9SNr4z0+A0JefvTmR60Zwf8XSEV7c=
github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ=
github.com/oze4/godaddygo v1.3.17 h1:J7LKj8a2XXYI7O/MJIhsscvaRf8/xlRDA9KAq0uY9Z4=
github.com/oze4/godaddygo v1.3.17/go.mod h1:8mlHQ5YqhPASKePDoR17pMLhz1i0w4jRJE4wbMlGD60=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=

View File

@ -54,6 +54,7 @@ import (
_ "git.happydns.org/happydns/sources/alwaysdata"
_ "git.happydns.org/happydns/sources/ddns"
_ "git.happydns.org/happydns/sources/gandi"
_ "git.happydns.org/happydns/sources/godaddy"
_ "git.happydns.org/happydns/sources/ovh"
_ "git.happydns.org/happydns/services/providers/google"

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

286
sources/godaddy/source.go Normal file
View File

@ -0,0 +1,286 @@
// Copyright or © or Copr. happyDNS (2021)
//
// contact@happydns.org
//
// This software is a computer program whose purpose is to provide a modern
// interface to interact with DNS systems.
//
// This software is governed by the CeCILL license under French law and abiding
// by the rules of distribution of free software. You can use, modify and/or
// redistribute the software under the terms of the CeCILL license as
// circulated by CEA, CNRS and INRIA at the following URL
// "http://www.cecill.info".
//
// As a counterpart to the access to the source code and rights to copy, modify
// and redistribute granted by the license, users are provided only with a
// limited warranty and the software's author, the holder of the economic
// rights, and the successive licensors have only limited liability.
//
// In this respect, the user's attention is drawn to the risks associated with
// loading, using, modifying and/or developing or reproducing the software by
// the user in light of its specific status of free software, that may mean
// that it is complicated to manipulate, and that also therefore means that it
// is reserved for developers and experienced professionals having in-depth
// computer knowledge. Users are therefore encouraged to load and test the
// software's suitability as regards their requirements in conditions enabling
// the security of their systems and/or data to be ensured and, more generally,
// to use and operate it in the same conditions as regards security.
//
// The fact that you are presently reading this means that you have had
// knowledge of the CeCILL license and that you accept its terms.
package godaddy // import "happydns.org/sources/godaddy"
import (
"context"
"fmt"
"log"
"strings"
"github.com/miekg/dns"
"github.com/oze4/godaddygo"
"git.happydns.org/happydns/model"
"git.happydns.org/happydns/sources"
"git.happydns.org/happydns/utils"
)
type GoDaddyAPI struct {
ApiKey string `json:"apiKey,omitempty" happydns:"label=Api Key,placeholder=xxxxxxxxxx,required"`
ApiSecret string `json:"apiSecret,omitempty" happydns:"label=Api Secret,placeholder=xxxxxxxxxx,required"`
}
func (s *GoDaddyAPI) ListAvailableTypes() (types []uint16) {
return []uint16{
dns.TypeA,
dns.TypeAAAA,
dns.TypeCNAME,
dns.TypeMX,
dns.TypeNS,
dns.TypeSOA,
dns.TypeSRV,
dns.TypeTXT,
}
}
func (s *GoDaddyAPI) newClient() (godaddygo.API, error) {
return godaddygo.NewProduction(
s.ApiKey,
s.ApiSecret,
)
}
func (s *GoDaddyAPI) ListDomains() (zones []string, err error) {
var client godaddygo.API
client, err = s.newClient()
if err != nil {
return
}
var domains []godaddygo.DomainSummary
domains, err = client.V1().ListDomains(context.Background())
if err != nil {
return
}
for _, domain := range domains {
zones = append(zones, dns.Fqdn(domain.Domain))
}
return
}
func (s *GoDaddyAPI) Validate() error {
var client godaddygo.API
client, err := s.newClient()
if err != nil {
return err
}
avlb, err := client.V1().CheckAvailability(context.Background(), "happydns.org", false)
if err != nil {
return err
}
if avlb.Domain != "happydns.org" {
return fmt.Errorf("GoDaddy API doesn't returns something usefull. Try update happyDNS or report bug.")
}
return nil
}
func (s *GoDaddyAPI) DomainExists(fqdn string) (err error) {
var client godaddygo.API
client, err = s.newClient()
if err != nil {
return
}
_, err = client.V1().Domain(strings.TrimSuffix(fqdn, ".")).GetDetails(context.Background())
return
}
func toRR(r *godaddygo.Record, origin string) (dns.RR, error) {
if r.Name == "@" {
r.Name = origin
} else {
r.Name = r.Name + "." + origin
}
if r.Protocol != "" {
r.Name = r.Protocol + "." + r.Name
}
if r.Service != "" {
r.Name = r.Service + "." + r.Name
}
if r.Type == "TXT" {
r.Data = "\"" + r.Data + "\""
}
str := fmt.Sprintf("$ORIGIN .\n%s %d IN %s ", r.Name, r.TTL, r.Type)
if r.Type == "SRV" {
str += fmt.Sprintf("%d %d %d %s", r.Priority, r.Weight, r.Port, r.Data)
} else if r.Type == "MX" {
str += fmt.Sprintf("%d %s", r.Priority, r.Data)
} else {
str += r.Data
}
return dns.NewRR(str)
}
func (s *GoDaddyAPI) ImportZone(dn *happydns.Domain) (rrs []dns.RR, err error) {
var client godaddygo.API
client, err = s.newClient()
if err != nil {
return
}
var records []godaddygo.Record
records, err = client.V1().Domain(strings.TrimSuffix(dn.DomainName, ".")).Records().List(context.Background())
for _, r := range records {
var rr dns.RR
rr, err = toRR(&r, dn.DomainName)
if err != nil {
return
}
rrs = append(rrs, rr)
}
return
}
func getSubdomain(dn *happydns.Domain, rr dns.RR) string {
str := strings.TrimSuffix(strings.TrimSuffix(rr.Header().Name, dn.DomainName), ".")
if len(str) == 0 {
return "@"
}
return str
}
func createGoDaddyRecord(rr dns.RR, dn *happydns.Domain) godaddygo.Record {
record := godaddygo.Record{
Name: getSubdomain(dn, rr),
TTL: int(rr.Header().Ttl),
Type: dns.Type(rr.Header().Rrtype).String(),
}
if mx, ok := rr.(*dns.MX); ok {
record.Priority = int(mx.Preference)
record.Data = strings.TrimSuffix(utils.DomainFQDN(mx.Mx, dn.DomainName), ".")
} else if srv, ok := rr.(*dns.SRV); ok {
record.Priority = int(srv.Priority)
record.Weight = int(srv.Weight)
record.Port = int(srv.Port)
record.Data = strings.TrimSuffix(utils.DomainFQDN(srv.Target, dn.DomainName), ".")
sname := strings.SplitN(record.Name, ".", 3)
if len(sname) == 3 && sname[0][0] == '_' && sname[1][0] == '_' {
record.Service = sname[0]
record.Protocol = sname[1]
record.Name = sname[2]
} else if len(sname) == 2 && sname[0][0] == '_' && sname[1][0] == '_' {
record.Service = sname[0]
record.Protocol = sname[1]
record.Name = "@"
}
} else if cname, ok := rr.(*dns.CNAME); ok {
record.Data = strings.TrimSuffix(utils.DomainFQDN(cname.Target, dn.DomainName), ".")
} else if ns, ok := rr.(*dns.NS); ok {
record.Data = strings.TrimSuffix(utils.DomainFQDN(ns.Ns, dn.DomainName), ".")
} else {
record.Data = strings.TrimPrefix(rr.String(), rr.Header().String())
}
return record
}
func (s *GoDaddyAPI) AddRR(dn *happydns.Domain, rr dns.RR) (err error) {
var client godaddygo.API
client, err = s.newClient()
if err != nil {
return
}
sup := createGoDaddyRecord(rr, dn)
err = client.V1().Domain(strings.TrimSuffix(dn.DomainName, ".")).Records().Add(context.Background(), []godaddygo.Record{sup})
return
}
func (s *GoDaddyAPI) DeleteRR(dn *happydns.Domain, rr dns.RR) (err error) {
var client godaddygo.API
client, err = s.newClient()
if err != nil {
return
}
del := createGoDaddyRecord(rr, dn)
// Apparently, we can't pass an empty array to ReplaceByType when Name=@, this doesn't delete the last record.
// So, passing the entire domain each time...
var records []godaddygo.Record
records, err = client.V1().Domain(strings.TrimSuffix(dn.DomainName, ".")).Records().List(context.Background())
if err != nil {
return
}
log.Println(records)
// Find the right record
for i, rec := range records {
if rec.Name == del.Name &&
rec.Data == del.Data &&
rec.Port == del.Port &&
rec.Priority == del.Priority &&
rec.Protocol == del.Protocol &&
rec.Service == del.Service &&
rec.Type == del.Type &&
rec.Weight == del.Weight {
records = append(records[:i], records[i+1:]...)
err = client.V1().Domain(strings.TrimSuffix(dn.DomainName, ".")).Records().Update(context.Background(), records)
return
}
}
err = fmt.Errorf("Unable to find the good record to delete in the zone.")
return
}
func (s *GoDaddyAPI) UpdateSOA(dn *happydns.Domain, newSOA *dns.SOA, refreshSerial bool) (err error) {
return fmt.Errorf("Not implemented yet")
}
func init() {
sources.RegisterSource(func() happydns.Source {
return &GoDaddyAPI{}
}, sources.SourceInfos{
Name: "GoDaddy",
Description: "American hosting provider.",
})
}

File diff suppressed because one or more lines are too long