Implement OVH API source

This commit is contained in:
nemunaire 2020-04-28 08:50:02 +02:00
parent 0f31d26875
commit dd12314385
6 changed files with 184 additions and 0 deletions

2
go.mod
View File

@ -6,5 +6,7 @@ require (
github.com/go-sql-driver/mysql v1.5.0
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/syndtr/goleveldb v1.0.0
gopkg.in/ini.v1 v1.55.0 // indirect
)

4
go.sum
View File

@ -12,6 +12,8 @@ github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
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/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@ -36,5 +38,7 @@ golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapK
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/ini.v1 v1.55.0 h1:E8yzL5unfpW3M6fz/eB7Cb5MQAYSZ7GKo4Qth+N2sgQ=
gopkg.in/ini.v1 v1.55.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -15,6 +15,7 @@ import (
leveldb "git.happydns.org/happydns/storage/leveldb"
_ "git.happydns.org/happydns/sources/ddns"
_ "git.happydns.org/happydns/sources/ovh"
)
type ResponseWriterPrefix struct {

File diff suppressed because one or more lines are too long

BIN
sources/ovh/OVHAPI.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

175
sources/ovh/source.go Normal file
View File

@ -0,0 +1,175 @@
package ovh // import "happydns.org/sources/ovh"
import (
"fmt"
"strings"
"github.com/miekg/dns"
"github.com/ovh/go-ovh/ovh"
"git.happydns.org/happydns/model"
"git.happydns.org/happydns/sources"
)
type OVHAPI struct {
Endpoint string `json:"endpoint,omitempty" happydns:"label=Endpoint,default=ovh-eu,choices=ovh-eu;ovh-us;ovh-ca;soyoustart-eu;soyoustart-ca;kimsufi-eu;kimsufi-ca,required"`
AppKey string `json:"appkey,omitempty" happydns:"label=Application Key,placeholder=xxxxxxxxxx,required"`
AppSecret string `json:"appsecret,omitempty" happydns:"label=Application Secret,placeholder=xxxxxxxxxx,required,secret"`
ConsumerKey string `json:"consumerkey,omitempty" happydns:"label=Consumer Key,placeholder=xxxxxxxxxx,required"`
}
func (s *OVHAPI) newClient() (*ovh.Client, error) {
return ovh.NewClient(
s.Endpoint,
s.AppKey,
s.AppSecret,
s.ConsumerKey,
)
}
func (s *OVHAPI) Validate() error {
client, err := s.newClient()
if err != nil {
return err
}
me := struct {
State string `json:"state"`
}{}
err = client.Get("/me", &me)
if err != nil {
return err
}
if me.State != "complete" {
return fmt.Errorf("API state returns is %q, expected \"complete\"", me.State)
}
return nil
}
func (s *OVHAPI) ImportZone(dn *happydns.Domain) (rrs []dns.RR, err error) {
var client *ovh.Client
client, err = s.newClient()
if err != nil {
return
}
var zone string
err = client.Get(fmt.Sprintf("/domain/zone/%s/export", strings.TrimSuffix(dn.DomainName, ".")), &zone)
if err != nil {
return
}
zp := dns.NewZoneParser(strings.NewReader(zone), dn.DomainName, "")
for rr, ok := zp.Next(); ok; rr, ok = zp.Next() {
rrs = append(rrs, rr)
}
if err = zp.Err(); err != nil {
return
}
return
}
type OVHRecord struct {
Id int64 `json:"id,omitempty"`
FieldType string `json:"fieldType"`
TTL uint32 `json:"ttl"`
Target string `json:"target"`
Zone string `json:"zone,omitempty"`
SubDomain string `json:"subDomain"`
}
func (s *OVHAPI) AddRR(dn *happydns.Domain, rr dns.RR) (err error) {
var client *ovh.Client
client, err = s.newClient()
if err != nil {
return
}
sup := OVHRecord{
SubDomain: ovhSubdomain(dn, rr),
FieldType: dns.Type(rr.Header().Rrtype).String(),
TTL: rr.Header().Ttl,
Target: strings.TrimPrefix(rr.String(), rr.Header().String()),
}
var res OVHRecord
err = client.Post(
fmt.Sprintf("/domain/zone/%s/record", strings.TrimSuffix(dn.DomainName, ".")),
sup, &res)
if err != nil {
return
}
err = client.Post(fmt.Sprintf("/domain/zone/%s/refresh", strings.TrimSuffix(dn.DomainName, ".")), nil, nil)
if err != nil {
return
}
return
}
func ovhSubdomain(dn *happydns.Domain, rr dns.RR) string {
return strings.TrimSuffix(strings.TrimSuffix(rr.Header().Name, dn.DomainName), ".")
}
func (s *OVHAPI) DeleteRR(dn *happydns.Domain, rr dns.RR) (err error) {
var client *ovh.Client
client, err = s.newClient()
if err != nil {
return
}
// Get all matching IDs
var ids []int64
err = client.Get(
fmt.Sprintf("/domain/zone/%s/record?fieldType=%s&subDomain=%s", strings.TrimSuffix(dn.DomainName, "."), dns.Type(rr.Header().Rrtype).String(), ovhSubdomain(dn, rr)),
&ids)
if err != nil {
return
}
// Find the right ID
for _, id := range ids {
var rec OVHRecord
err = client.Get(
fmt.Sprintf("/domain/zone/%s/record/%d", strings.TrimSuffix(dn.DomainName, "."), id),
&rec)
if err != nil {
return
}
if rec.Target == strings.TrimPrefix(rr.String(), rr.Header().String()) {
err = client.Delete(fmt.Sprintf("/domain/zone/%s/record/%d", strings.TrimSuffix(dn.DomainName, "."), id), nil)
if err != nil {
return
}
err = client.Post(fmt.Sprintf("/domain/zone/%s/refresh", strings.TrimSuffix(dn.DomainName, ".")), nil, nil)
if err != nil {
return
}
return
}
}
return
}
func init() {
sources.RegisterSource("git.happydns.org/happydns/sources/ovh/OVHAPI", func() happydns.Source {
return &OVHAPI{}
}, sources.SourceInfos{
Name: "OVH",
Description: "Hosting",
})
}