mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
PORKBUN: Add registrar support (#2542)
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
This commit is contained in:
@ -53,7 +53,7 @@ If a feature is definitively not supported for whatever reason, we would also li
|
|||||||
| [`ORACLE`](providers/oracle.md) | ❌ | ✅ | ❌ | ✅ | ✅ | ❔ | ❔ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ |
|
| [`ORACLE`](providers/oracle.md) | ❌ | ✅ | ❌ | ✅ | ✅ | ❔ | ❔ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ |
|
||||||
| [`OVH`](providers/ovh.md) | ❌ | ✅ | ✅ | ❌ | ✅ | ❔ | ❔ | ❔ | ❌ | ❔ | ✅ | ✅ | ✅ | ❔ | ✅ | ❌ | ✅ | ✅ |
|
| [`OVH`](providers/ovh.md) | ❌ | ✅ | ✅ | ❌ | ✅ | ❔ | ❔ | ❔ | ❌ | ❔ | ✅ | ✅ | ✅ | ❔ | ✅ | ❌ | ✅ | ✅ |
|
||||||
| [`PACKETFRAME`](providers/packetframe.md) | ❌ | ✅ | ❌ | ❔ | ❔ | ❔ | ❔ | ❔ | ✅ | ❔ | ✅ | ❔ | ❔ | ❔ | ❌ | ❌ | ✅ | ❔ |
|
| [`PACKETFRAME`](providers/packetframe.md) | ❌ | ✅ | ❌ | ❔ | ❔ | ❔ | ❔ | ❔ | ✅ | ❔ | ✅ | ❔ | ❔ | ❔ | ❌ | ❌ | ✅ | ❔ |
|
||||||
| [`PORKBUN`](providers/porkbun.md) | ❌ | ✅ | ❌ | ✅ | ❔ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ |
|
| [`PORKBUN`](providers/porkbun.md) | ❌ | ✅ | ✅ | ✅ | ❔ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ |
|
||||||
| [`POWERDNS`](providers/powerdns.md) | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
| [`POWERDNS`](providers/powerdns.md) | ❌ | ✅ | ❌ | ✅ | ✅ | ✅ | ❔ | ✅ | ✅ | ❔ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||||
| [`ROUTE53`](providers/route53.md) | ✅ | ✅ | ✅ | ❌ | ✅ | ❔ | ❌ | ❔ | ✅ | ❔ | ✅ | ❔ | ❔ | ❔ | ✅ | ✅ | ✅ | ✅ |
|
| [`ROUTE53`](providers/route53.md) | ✅ | ✅ | ✅ | ❌ | ✅ | ❔ | ❌ | ❔ | ✅ | ❔ | ✅ | ❔ | ❔ | ❔ | ✅ | ✅ | ✅ | ✅ |
|
||||||
| [`RWTH`](providers/rwth.md) | ❌ | ✅ | ❌ | ❌ | ✅ | ❔ | ❌ | ❌ | ✅ | ❔ | ✅ | ✅ | ❌ | ❔ | ❌ | ❌ | ✅ | ✅ |
|
| [`RWTH`](providers/rwth.md) | ❌ | ✅ | ❌ | ❌ | ✅ | ❔ | ❌ | ❌ | ✅ | ❔ | ✅ | ✅ | ❌ | ❔ | ❌ | ❌ | ✅ | ✅ |
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,7 +19,7 @@ type porkbunProvider struct {
|
|||||||
secretKey string
|
secretKey string
|
||||||
}
|
}
|
||||||
|
|
||||||
type requestParams map[string]string
|
type requestParams map[string]any
|
||||||
|
|
||||||
type errorResponse struct {
|
type errorResponse struct {
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
@ -40,6 +41,11 @@ type recordResponse struct {
|
|||||||
Records []domainRecord `json:"records"`
|
Records []domainRecord `json:"records"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type nsResponse struct {
|
||||||
|
Status string `json:"status"`
|
||||||
|
Nameservers []string `json:"ns"`
|
||||||
|
}
|
||||||
|
|
||||||
func (c *porkbunProvider) post(endpoint string, params requestParams) ([]byte, error) {
|
func (c *porkbunProvider) post(endpoint string, params requestParams) ([]byte, error) {
|
||||||
params["apikey"] = c.apiKey
|
params["apikey"] = c.apiKey
|
||||||
params["secretapikey"] = c.secretKey
|
params["secretapikey"] = c.secretKey
|
||||||
@ -82,7 +88,7 @@ func (c *porkbunProvider) ping() error {
|
|||||||
|
|
||||||
func (c *porkbunProvider) createRecord(domain string, rec requestParams) error {
|
func (c *porkbunProvider) createRecord(domain string, rec requestParams) error {
|
||||||
if _, err := c.post("/dns/create/"+domain, rec); err != nil {
|
if _, err := c.post("/dns/create/"+domain, rec); err != nil {
|
||||||
return fmt.Errorf("failed create record (porkbun): %s", err)
|
return fmt.Errorf("failed create record (porkbun): %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -90,14 +96,14 @@ func (c *porkbunProvider) createRecord(domain string, rec requestParams) error {
|
|||||||
func (c *porkbunProvider) deleteRecord(domain string, recordID string) error {
|
func (c *porkbunProvider) deleteRecord(domain string, recordID string) error {
|
||||||
params := requestParams{}
|
params := requestParams{}
|
||||||
if _, err := c.post(fmt.Sprintf("/dns/delete/%s/%s", domain, recordID), params); err != nil {
|
if _, err := c.post(fmt.Sprintf("/dns/delete/%s/%s", domain, recordID), params); err != nil {
|
||||||
return fmt.Errorf("failed delete record (porkbun): %s", err)
|
return fmt.Errorf("failed delete record (porkbun): %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *porkbunProvider) modifyRecord(domain string, recordID string, rec requestParams) error {
|
func (c *porkbunProvider) modifyRecord(domain string, recordID string, rec requestParams) error {
|
||||||
if _, err := c.post(fmt.Sprintf("/dns/edit/%s/%s", domain, recordID), rec); err != nil {
|
if _, err := c.post(fmt.Sprintf("/dns/edit/%s/%s", domain, recordID), rec); err != nil {
|
||||||
return fmt.Errorf("failed update (porkbun): %s", err)
|
return fmt.Errorf("failed update (porkbun): %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -106,7 +112,7 @@ func (c *porkbunProvider) getRecords(domain string) ([]domainRecord, error) {
|
|||||||
params := requestParams{}
|
params := requestParams{}
|
||||||
var bodyString, err = c.post("/dns/retrieve/"+domain, params)
|
var bodyString, err = c.post("/dns/retrieve/"+domain, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed fetching record list from porkbun: %s", err)
|
return nil, fmt.Errorf("failed fetching record list from porkbun: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var dr recordResponse
|
var dr recordResponse
|
||||||
@ -121,3 +127,26 @@ func (c *porkbunProvider) getRecords(domain string) ([]domainRecord, error) {
|
|||||||
}
|
}
|
||||||
return records, nil
|
return records, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *porkbunProvider) getNameservers(domain string) ([]string, error) {
|
||||||
|
params := requestParams{}
|
||||||
|
var bodyString, err = c.post(fmt.Sprintf("/domain/getNs/%s", domain), params)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed fetching nameserver list from porkbun: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var ns nsResponse
|
||||||
|
json.Unmarshal(bodyString, &ns)
|
||||||
|
|
||||||
|
sort.Strings(ns.Nameservers)
|
||||||
|
return ns.Nameservers, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *porkbunProvider) updateNameservers(ns []string, domain string) error {
|
||||||
|
params := requestParams{}
|
||||||
|
params["ns"] = ns
|
||||||
|
if _, err := c.post(fmt.Sprintf("/domain/updateNs/%s", domain), params); err != nil {
|
||||||
|
return fmt.Errorf("failed NS update (porkbun): %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -3,6 +3,7 @@ package porkbun
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -25,8 +26,16 @@ var defaultNS = []string{
|
|||||||
"salvador.ns.porkbun.com",
|
"salvador.ns.porkbun.com",
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPorkbun creates the provider.
|
func newReg(conf map[string]string) (providers.Registrar, error) {
|
||||||
func NewPorkbun(m map[string]string, metadata json.RawMessage) (providers.DNSServiceProvider, error) {
|
return newPorkbun(conf, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDsp(conf map[string]string, metadata json.RawMessage) (providers.DNSServiceProvider, error) {
|
||||||
|
return newPorkbun(conf, metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
// newPorkbun creates the provider.
|
||||||
|
func newPorkbun(m map[string]string, metadata json.RawMessage) (*porkbunProvider, error) {
|
||||||
c := &porkbunProvider{}
|
c := &porkbunProvider{}
|
||||||
|
|
||||||
c.apiKey, c.secretKey = m["api_key"], m["secret_key"]
|
c.apiKey, c.secretKey = m["api_key"], m["secret_key"]
|
||||||
@ -63,8 +72,9 @@ var features = providers.DocumentationNotes{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
providers.RegisterRegistrarType("PORKBUN", newReg)
|
||||||
fns := providers.DspFuncs{
|
fns := providers.DspFuncs{
|
||||||
Initializer: NewPorkbun,
|
Initializer: newDsp,
|
||||||
RecordAuditor: AuditRecords,
|
RecordAuditor: AuditRecords,
|
||||||
}
|
}
|
||||||
providers.RegisterDomainServiceProviderType("PORKBUN", fns, features)
|
providers.RegisterDomainServiceProviderType("PORKBUN", fns, features)
|
||||||
@ -317,3 +327,31 @@ func fixTTL(ttl uint32) uint32 {
|
|||||||
}
|
}
|
||||||
return minimumTTL
|
return minimumTTL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *porkbunProvider) GetRegistrarCorrections(dc *models.DomainConfig) ([]*models.Correction, error) {
|
||||||
|
nss, err := c.getNameservers(dc.Name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
foundNameservers := strings.Join(nss, ",")
|
||||||
|
|
||||||
|
expected := []string{}
|
||||||
|
for _, ns := range dc.Nameservers {
|
||||||
|
expected = append(expected, ns.Name)
|
||||||
|
}
|
||||||
|
sort.Strings(expected)
|
||||||
|
expectedNameservers := strings.Join(expected, ",")
|
||||||
|
|
||||||
|
if foundNameservers == expectedNameservers {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return []*models.Correction{
|
||||||
|
{
|
||||||
|
Msg: fmt.Sprintf("Update nameservers %s -> %s", foundNameservers, expectedNameservers),
|
||||||
|
F: func() error {
|
||||||
|
return c.updateNameservers(expected, dc.Name)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user