You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
3.2 KiB
Go

package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
type DNSRecord struct {
ID string `json:"id,omitempty"`
Type string `json:"type"`
Name string `json:"name"`
Content string `json:"content"`
TTL int `json:"ttl"`
}
type DNSListResponse struct {
Result []DNSRecord `json:"result"`
}
type CreateOrUpdateResponse struct {
Success bool `json:"success"`
Errors []struct {
Message string `json:"message"`
} `json:"errors"`
}
// OverwriteDNSRecord overwrites or creates a DNS record using Cloudflare's API.
func OverwriteDNSRecord(apiToken, zoneID, recordName, recordType, recordContent string, ttl int) error {
baseURL := fmt.Sprintf("https://api.cloudflare.com/client/v4/zones/%s/dns_records", zoneID)
// Fetch existing DNS records
req, err := http.NewRequest("GET", baseURL, nil)
if err != nil {
return fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+apiToken)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("failed to fetch DNS records: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("failed to fetch DNS records: status code %d", resp.StatusCode)
}
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("failed to read response body: %w", err)
}
var listResponse DNSListResponse
if err := json.Unmarshal(body, &listResponse); err != nil {
return fmt.Errorf("failed to parse response body: %w", err)
}
var existingRecordID string
for _, record := range listResponse.Result {
if record.Name == recordName && record.Type == recordType {
existingRecordID = record.ID
break
}
}
// Prepare the DNS record payload
dnsRecord := DNSRecord{
Type: recordType,
Name: recordName,
Content: recordContent,
TTL: ttl,
}
var method string
var url string
if existingRecordID != "" {
// Update existing record
method = "PUT"
url = fmt.Sprintf("%s/%s", baseURL, existingRecordID)
} else {
// Create a new record
method = "POST"
url = baseURL
}
payload, err := json.Marshal(dnsRecord)
if err != nil {
return fmt.Errorf("failed to marshal JSON: %w", err)
}
req, err = http.NewRequest(method, url, bytes.NewBuffer(payload))
if err != nil {
return fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+apiToken)
req.Header.Set("Content-Type", "application/json")
resp, err = client.Do(req)
if err != nil {
return fmt.Errorf("failed to execute request: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
return fmt.Errorf("request failed with status code %d", resp.StatusCode)
}
var result CreateOrUpdateResponse
body, err = ioutil.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("failed to read response body: %w", err)
}
if err := json.Unmarshal(body, &result); err != nil {
return fmt.Errorf("failed to parse response body: %w", err)
}
if !result.Success {
return fmt.Errorf("request failed with error: %v", result.Errors)
}
log.Printf("DNS record %s successfully %s", recordName, method)
return nil
}