feat: dns provider ionos
This commit is contained in:
213
pkg/dnsProvider/ionos/api/ionosAPI.go
Normal file
213
pkg/dnsProvider/ionos/api/ionosAPI.go
Normal file
@@ -0,0 +1,213 @@
|
||||
package ionosAPI
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"realdnydns/model/common"
|
||||
)
|
||||
|
||||
/**
|
||||
* Docs: https://developer.hosting.ionos.com/docs/dns
|
||||
*/
|
||||
type IonosAPI interface {
|
||||
GetARecord(tld string, subdomain string) (*common.ARecord, error)
|
||||
SetARecord(tld string, subdomain string, ip net.IP, ttl int, prio int, disabled bool) (*common.ARecord, error)
|
||||
GetZoneId(tld string) (string, error)
|
||||
GetRecordId(zoneId string, tld string, subdomain string, recordType string) (string, error)
|
||||
HttpCall(method string, url string, body io.Reader) (*http.Response, error)
|
||||
}
|
||||
|
||||
type IonosAPIImpl struct {
|
||||
APIKey string
|
||||
BaseURL string
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
type ZonesResponse []struct {
|
||||
Name string `json:"name"`
|
||||
Id string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type ZoneResponse struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Records []RecordResponse `json:"records"`
|
||||
}
|
||||
|
||||
type RecordResponse struct {
|
||||
Id string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
RootName string `json:"rootName"`
|
||||
Type string `json:"type"`
|
||||
Content string `json:"content"`
|
||||
ChangeDate string `json:"changeDate"`
|
||||
TTL int `json:"ttl"`
|
||||
Prio int `json:"prio"`
|
||||
Disabled bool `json:"disabled"`
|
||||
}
|
||||
|
||||
type ChangeRecord struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
Content string `json:"content"`
|
||||
TTL int `json:"ttl"`
|
||||
Prio int `json:"prio"`
|
||||
Disabled bool `json:"disabled"`
|
||||
}
|
||||
|
||||
type ChangeRecordRequest struct {
|
||||
Content string `json:"content"`
|
||||
TTL int `json:"ttl"`
|
||||
Prio int `json:"prio"`
|
||||
Disabled bool `json:"disabled"`
|
||||
}
|
||||
|
||||
func New(APIKey string, BaseURL string) IonosAPI {
|
||||
return &IonosAPIImpl{
|
||||
APIKey: APIKey,
|
||||
BaseURL: BaseURL,
|
||||
HTTPClient: &http.Client{},
|
||||
}
|
||||
}
|
||||
|
||||
func (i *IonosAPIImpl) HttpCall(method string, url string, body io.Reader) (*http.Response, error) {
|
||||
req, err := http.NewRequest(method, i.BaseURL+url, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Add("X-API-Key", i.APIKey)
|
||||
|
||||
return i.HTTPClient.Do(req)
|
||||
}
|
||||
|
||||
func (i *IonosAPIImpl) GetZoneId(tld string) (string, error) {
|
||||
res, err := i.HttpCall("GET", "/v1/zones", nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
responseBody := make([]byte, res.ContentLength)
|
||||
res.Body.Read(responseBody)
|
||||
|
||||
zones := []ZoneResponse{}
|
||||
json.Unmarshal(responseBody, &zones)
|
||||
|
||||
for _, z := range zones {
|
||||
if z.Name == tld {
|
||||
return z.Id, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", errors.New("zone not found")
|
||||
}
|
||||
|
||||
func (i *IonosAPIImpl) GetRecordId(zoneId string, tld string, subdomain string, recordType string) (string, error) {
|
||||
res, err := i.HttpCall("GET", "/v1/zones/"+zoneId, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
responseBody := make([]byte, res.ContentLength)
|
||||
res.Body.Read(responseBody)
|
||||
|
||||
zone := ZoneResponse{}
|
||||
json.Unmarshal(responseBody, &zone)
|
||||
|
||||
var domain string
|
||||
if subdomain != "" {
|
||||
domain = subdomain + "." + tld
|
||||
} else {
|
||||
domain = tld
|
||||
}
|
||||
|
||||
for _, record := range zone.Records {
|
||||
if record.Type == recordType && record.Name == domain {
|
||||
return record.Id, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", errors.New("record not found")
|
||||
}
|
||||
|
||||
func (i *IonosAPIImpl) SetARecord(tld string, subdomain string, ip net.IP, ttl int, prio int, disabled bool) (*common.ARecord, error) {
|
||||
zoneId, err := i.GetZoneId(tld)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
recordId, err := i.GetRecordId(zoneId, tld, subdomain, "A")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
changeRecordRequest, err := json.Marshal(ChangeRecordRequest{
|
||||
Content: ip.String(),
|
||||
TTL: ttl,
|
||||
Prio: prio,
|
||||
Disabled: false,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := i.HttpCall("PUT", "/v1/zones/"+zoneId+"/records/"+recordId, bytes.NewReader(changeRecordRequest))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if res.StatusCode != 200 {
|
||||
return nil, errors.New("error updating record")
|
||||
}
|
||||
|
||||
responseBody := make([]byte, res.ContentLength)
|
||||
res.Body.Read(responseBody)
|
||||
|
||||
changeRecord := ChangeRecord{}
|
||||
json.Unmarshal(responseBody, &changeRecord)
|
||||
|
||||
return &common.ARecord{
|
||||
Domain: changeRecord.Name,
|
||||
IP: changeRecord.Content,
|
||||
TTL: changeRecord.TTL,
|
||||
Prio: changeRecord.Prio,
|
||||
Disabled: changeRecord.Disabled,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (ionos *IonosAPIImpl) GetARecord(tld string, subdomain string) (*common.ARecord, error) {
|
||||
zoneId, err := ionos.GetZoneId(tld)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
recordId, err := ionos.GetRecordId(zoneId, tld, subdomain, "A")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := ionos.HttpCall("GET", "/v1/zones/"+zoneId+"/records/"+recordId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
responseBody := make([]byte, res.ContentLength)
|
||||
res.Body.Read(responseBody)
|
||||
|
||||
record := RecordResponse{}
|
||||
json.Unmarshal(responseBody, &record)
|
||||
|
||||
return &common.ARecord{
|
||||
Domain: record.Name,
|
||||
IP: record.Content,
|
||||
TTL: record.TTL,
|
||||
Prio: record.Prio,
|
||||
Disabled: record.Disabled,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user