Skip to content

Commit

Permalink
chore: rely on record id & lookup queries when missing to more reliab…
Browse files Browse the repository at this point in the history
…ly update existing records (#3)
  • Loading branch information
Niallfitzy1 authored Sep 6, 2023
1 parent f7c6860 commit c5d0f88
Show file tree
Hide file tree
Showing 10 changed files with 514 additions and 372 deletions.
File renamed without changes.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
_gitignore/
.env
.vscode/
.vscode/
.idea
134 changes: 0 additions & 134 deletions _test/integration_test.go

This file was deleted.

147 changes: 147 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package porkbun

import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"github.com/libdns/libdns"
"io"
"log"
"net/http"
"net/url"
"strconv"
"strings"
"time"
)

const ApiBase = "https://porkbun.com/api/json/v3"

// LibdnsZoneToPorkbunDomain Strips the trailing dot from a Zone
func LibdnsZoneToPorkbunDomain(zone string) string {
return strings.TrimSuffix(zone, ".")
}

// CheckCredentials allows verifying credentials work in test scripts
func (p *Provider) CheckCredentials(_ context.Context) (string, error) {
credentialJson, err := json.Marshal(p.getCredentials())
if err != nil {
return "", err
}

response, err := MakeApiRequest("/ping", bytes.NewReader(credentialJson), pkbnPingResponse{})

if err != nil {
return "", err
}

if response.Status != "SUCCESS" {
return "", err
}

return response.YourIP, nil
}

func (p *Provider) getCredentials() ApiCredentials {
return ApiCredentials{p.APIKey, p.APISecretKey}
}

func (p *Provider) getMatchingRecord(r libdns.Record, zone string) ([]libdns.Record, error) {
var recs []libdns.Record
trimmedZone := LibdnsZoneToPorkbunDomain(zone)

credentialJson, err := json.Marshal(p.getCredentials())
if err != nil {
return recs, err
}
endpoint := fmt.Sprintf("/dns/retrieveByNameType/%s/%s/%s", trimmedZone, r.Type, r.Name)
response, err := MakeApiRequest(endpoint, bytes.NewReader(credentialJson), pkbnRecordsResponse{})

if err != nil {
return recs, err
}

recs = make([]libdns.Record, 0, len(response.Records))
for _, rec := range response.Records {
recs = append(recs, rec.toLibdnsRecord(zone))
}
return recs, nil
}

// UpdateRecords adds records to the zone. It returns the records that were added.
func (p *Provider) updateRecords(_ context.Context, zone string, records []libdns.Record) ([]libdns.Record, error) {
credentials := p.getCredentials()
trimmedZone := LibdnsZoneToPorkbunDomain(zone)

var createdRecords []libdns.Record

for _, record := range records {
if record.TTL/time.Second < 600 {
record.TTL = 600 * time.Second
}
ttlInSeconds := int(record.TTL / time.Second)
trimmedName := libdns.RelativeName(record.Name, zone)

reqBody := pkbnRecordPayload{&credentials, record.Value, trimmedName, strconv.Itoa(ttlInSeconds), record.Type}
reqJson, err := json.Marshal(reqBody)
if err != nil {
return nil, err
}
response, err := MakeApiRequest(fmt.Sprintf("/dns/edit/%s/%s", trimmedZone, record.ID), bytes.NewReader(reqJson), pkbnResponseStatus{})
if err != nil {
return nil, err
}

if response.Status != "SUCCESS" {
return nil, err
}
createdRecords = append(createdRecords, record)
}

return createdRecords, nil
}

func MakeApiRequest[T any](endpoint string, body io.Reader, responseType T) (T, error) {
client := http.Client{}

fullUrl := ApiBase + endpoint
u, err := url.Parse(fullUrl)
if err != nil {
return responseType, err
}

req, err := http.NewRequest("POST", u.String(), body)
if err != nil {
return responseType, err
}
resp, err := client.Do(req)
if err != nil {
return responseType, err
}
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
log.Fatal("Couldn't close body")
}
}(resp.Body)

if resp.StatusCode != http.StatusOK {
bodyBytes, _ := io.ReadAll(resp.Body)
err = errors.New("Invalid http response status, " + string(bodyBytes))
return responseType, err
}

result, err := io.ReadAll(resp.Body)
if err != nil {
return responseType, err
}

err = json.Unmarshal(result, &responseType)

if err != nil {
return responseType, err
}

return responseType, nil
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ module github.com/libdns/porkbun
go 1.20

require github.com/libdns/libdns v0.2.1

require github.com/joho/godotenv v1.5.1
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
Loading

0 comments on commit c5d0f88

Please sign in to comment.