305 lines
9.4 KiB
Go
305 lines
9.4 KiB
Go
package cloudflare
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
|
|
"agent-wdd/log"
|
|
)
|
|
|
|
// DNSRecord represents a DNS record in Cloudflare
|
|
type DNSRecord struct {
|
|
ID string `json:"id,omitempty"`
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
Content string `json:"content"`
|
|
Priority int `json:"priority,omitempty"`
|
|
Proxiable bool `json:"proxiable,omitempty"`
|
|
Proxied bool `json:"proxied"`
|
|
TTL int `json:"ttl"`
|
|
Settings map[string]interface{} `json:"settings,omitempty"`
|
|
Meta map[string]interface{} `json:"meta,omitempty"`
|
|
Comment string `json:"comment,omitempty"`
|
|
Tags []string `json:"tags,omitempty"`
|
|
CreatedOn string `json:"created_on,omitempty"`
|
|
ModifiedOn string `json:"modified_on,omitempty"`
|
|
CommentModifiedOn string `json:"comment_modified_on,omitempty"`
|
|
}
|
|
|
|
// DNSRecordFilter represents filters for listing DNS records
|
|
type DNSRecordFilter struct {
|
|
Type string
|
|
Name string
|
|
Content string
|
|
Page int
|
|
PerPage int
|
|
Order string
|
|
Direction string
|
|
Match string
|
|
}
|
|
|
|
// ListDNSRecords retrieves all DNS records for a zone
|
|
//
|
|
// Parameters:
|
|
// - zoneID: The zone ID
|
|
// - filter: Optional filter to apply to the DNS records list
|
|
//
|
|
// Returns:
|
|
// - []DNSRecord: List of DNS records
|
|
// - error: Any errors that occurred during the request
|
|
func (c *CloudflareClient) ListDNSRecords(zoneID string, filter *DNSRecordFilter) ([]DNSRecord, error) {
|
|
log.Debug("Listing DNS records for zone ID: %s with filter: %+v", zoneID, filter)
|
|
|
|
// Build URL and query parameters
|
|
endpoint := fmt.Sprintf("%s/zones/%s/dns_records", c.baseURL, zoneID)
|
|
u, err := url.Parse(endpoint)
|
|
if err != nil {
|
|
log.Error("Failed to parse URL: %v", err)
|
|
return nil, fmt.Errorf("failed to parse URL: %w", err)
|
|
}
|
|
|
|
q := u.Query()
|
|
if filter != nil {
|
|
if filter.Type != "" {
|
|
q.Add("type", filter.Type)
|
|
}
|
|
if filter.Name != "" {
|
|
q.Add("name", filter.Name)
|
|
}
|
|
if filter.Content != "" {
|
|
q.Add("content", filter.Content)
|
|
}
|
|
if filter.Page > 0 {
|
|
q.Add("page", strconv.Itoa(filter.Page))
|
|
}
|
|
if filter.PerPage > 0 {
|
|
q.Add("per_page", strconv.Itoa(filter.PerPage))
|
|
}
|
|
if filter.Order != "" {
|
|
q.Add("order", filter.Order)
|
|
}
|
|
if filter.Direction != "" {
|
|
q.Add("direction", filter.Direction)
|
|
}
|
|
if filter.Match != "" {
|
|
q.Add("match", filter.Match)
|
|
}
|
|
}
|
|
u.RawQuery = q.Encode()
|
|
|
|
// Make request
|
|
resp, err := c.doRequest(http.MethodGet, u.String(), nil)
|
|
if err != nil {
|
|
log.Error("Failed to list DNS records: %v", err)
|
|
return nil, fmt.Errorf("failed to list DNS records: %w", err)
|
|
}
|
|
|
|
// Parse response
|
|
var records []DNSRecord
|
|
result, err := json.Marshal(resp.Result)
|
|
if err != nil {
|
|
log.Error("Failed to marshal result: %v", err)
|
|
return nil, fmt.Errorf("failed to marshal result: %w", err)
|
|
}
|
|
|
|
if err := json.Unmarshal(result, &records); err != nil {
|
|
log.Error("Failed to unmarshal DNS records: %v", err)
|
|
return nil, fmt.Errorf("failed to unmarshal DNS records: %w", err)
|
|
}
|
|
|
|
log.Info("Successfully retrieved %d DNS records for zone ID: %s", len(records), zoneID)
|
|
return records, nil
|
|
}
|
|
|
|
// CreateDNSRecord creates a new DNS record in the specified zone
|
|
//
|
|
// Parameters:
|
|
// - zoneID: The zone ID
|
|
// - record: The DNS record to create
|
|
//
|
|
// Returns:
|
|
// - *DNSRecord: The created DNS record
|
|
// - error: Any errors that occurred during the request
|
|
func (c *CloudflareClient) CreateDNSRecord(zoneID string, record DNSRecord) (*DNSRecord, error) {
|
|
log.Debug("Creating DNS record in zone ID: %s with data: %+v", zoneID, record)
|
|
|
|
// Build URL
|
|
endpoint := fmt.Sprintf("%s/zones/%s/dns_records", c.baseURL, zoneID)
|
|
|
|
// Make request
|
|
resp, err := c.doRequest(http.MethodPost, endpoint, record)
|
|
if err != nil {
|
|
log.Error("Failed to create DNS record: %v", err)
|
|
return nil, fmt.Errorf("failed to create DNS record: %w", err)
|
|
}
|
|
|
|
// Parse response
|
|
var createdRecord DNSRecord
|
|
result, err := json.Marshal(resp.Result)
|
|
if err != nil {
|
|
log.Error("Failed to marshal result: %v", err)
|
|
return nil, fmt.Errorf("failed to marshal result: %w", err)
|
|
}
|
|
|
|
if err := json.Unmarshal(result, &createdRecord); err != nil {
|
|
log.Error("Failed to unmarshal created DNS record: %v", err)
|
|
return nil, fmt.Errorf("failed to unmarshal created DNS record: %w", err)
|
|
}
|
|
|
|
log.Info("Successfully created DNS record: %s (%s) in zone ID: %s", createdRecord.Name, createdRecord.ID, zoneID)
|
|
return &createdRecord, nil
|
|
}
|
|
|
|
// GetDNSRecord retrieves a specific DNS record by ID
|
|
//
|
|
// Parameters:
|
|
// - zoneID: The zone ID
|
|
// - recordID: The DNS record ID
|
|
//
|
|
// Returns:
|
|
// - *DNSRecord: The DNS record
|
|
// - error: Any errors that occurred during the request
|
|
func (c *CloudflareClient) GetDNSRecord(zoneID, recordID string) (*DNSRecord, error) {
|
|
log.Debug("Getting DNS record ID: %s in zone ID: %s", recordID, zoneID)
|
|
|
|
// Build URL
|
|
endpoint := fmt.Sprintf("%s/zones/%s/dns_records/%s", c.baseURL, zoneID, recordID)
|
|
|
|
// Make request
|
|
resp, err := c.doRequest(http.MethodGet, endpoint, nil)
|
|
if err != nil {
|
|
log.Error("Failed to get DNS record: %v", err)
|
|
return nil, fmt.Errorf("failed to get DNS record: %w", err)
|
|
}
|
|
|
|
// Parse response
|
|
var record DNSRecord
|
|
result, err := json.Marshal(resp.Result)
|
|
if err != nil {
|
|
log.Error("Failed to marshal result: %v", err)
|
|
return nil, fmt.Errorf("failed to marshal result: %w", err)
|
|
}
|
|
|
|
if err := json.Unmarshal(result, &record); err != nil {
|
|
log.Error("Failed to unmarshal DNS record: %v", err)
|
|
return nil, fmt.Errorf("failed to unmarshal DNS record: %w", err)
|
|
}
|
|
|
|
log.Info("Successfully retrieved DNS record: %s (%s) from zone ID: %s", record.Name, record.ID, zoneID)
|
|
return &record, nil
|
|
}
|
|
|
|
// UpdateDNSRecord updates an existing DNS record
|
|
//
|
|
// Parameters:
|
|
// - zoneID: The zone ID
|
|
// - recordID: The DNS record ID
|
|
// - record: The updated DNS record data
|
|
//
|
|
// Returns:
|
|
// - *DNSRecord: The updated DNS record
|
|
// - error: Any errors that occurred during the request
|
|
func (c *CloudflareClient) UpdateDNSRecord(zoneID, recordID string, record DNSRecord) (*DNSRecord, error) {
|
|
log.Debug("Updating DNS record ID: %s in zone ID: %s with data: %+v", recordID, zoneID, record)
|
|
|
|
// Build URL
|
|
endpoint := fmt.Sprintf("%s/zones/%s/dns_records/%s", c.baseURL, zoneID, recordID)
|
|
|
|
// Make request
|
|
resp, err := c.doRequest(http.MethodPut, endpoint, record)
|
|
if err != nil {
|
|
log.Error("Failed to update DNS record: %v", err)
|
|
return nil, fmt.Errorf("failed to update DNS record: %w", err)
|
|
}
|
|
|
|
// Parse response
|
|
var updatedRecord DNSRecord
|
|
result, err := json.Marshal(resp.Result)
|
|
if err != nil {
|
|
log.Error("Failed to marshal result: %v", err)
|
|
return nil, fmt.Errorf("failed to marshal result: %w", err)
|
|
}
|
|
|
|
if err := json.Unmarshal(result, &updatedRecord); err != nil {
|
|
log.Error("Failed to unmarshal updated DNS record: %v", err)
|
|
return nil, fmt.Errorf("failed to unmarshal updated DNS record: %w", err)
|
|
}
|
|
|
|
log.Info("Successfully updated DNS record: %s (%s) in zone ID: %s", updatedRecord.Name, updatedRecord.ID, zoneID)
|
|
return &updatedRecord, nil
|
|
}
|
|
|
|
// DeleteDNSRecord deletes a DNS record
|
|
//
|
|
// Parameters:
|
|
// - zoneID: The zone ID
|
|
// - recordID: The DNS record ID
|
|
//
|
|
// Returns:
|
|
// - bool: True if the record was deleted successfully
|
|
// - error: Any errors that occurred during the request
|
|
func (c *CloudflareClient) DeleteDNSRecord(zoneID, recordID string) (bool, error) {
|
|
log.Debug("Deleting DNS record ID: %s in zone ID: %s", recordID, zoneID)
|
|
|
|
// Build URL
|
|
endpoint := fmt.Sprintf("%s/zones/%s/dns_records/%s", c.baseURL, zoneID, recordID)
|
|
|
|
// Make request
|
|
resp, err := c.doRequest(http.MethodDelete, endpoint, nil)
|
|
if err != nil {
|
|
log.Error("Failed to delete DNS record: %v", err)
|
|
return false, fmt.Errorf("failed to delete DNS record: %w", err)
|
|
}
|
|
|
|
// Parse response
|
|
result, ok := resp.Result.(map[string]interface{})
|
|
if !ok {
|
|
log.Error("Unexpected response format for DNS record deletion")
|
|
return false, fmt.Errorf("unexpected response format for DNS record deletion")
|
|
}
|
|
|
|
id, ok := result["id"].(string)
|
|
if !ok {
|
|
log.Error("Failed to extract ID from deletion response")
|
|
return false, fmt.Errorf("failed to extract ID from deletion response")
|
|
}
|
|
|
|
log.Info("Successfully deleted DNS record ID: %s from zone ID: %s", id, zoneID)
|
|
return true, nil
|
|
}
|
|
|
|
// FindDNSRecord finds a DNS record by name and type
|
|
//
|
|
// Parameters:
|
|
// - zoneID: The zone ID
|
|
// - name: The DNS record name
|
|
// - recordType: The DNS record type (A, AAAA, CNAME, etc.)
|
|
//
|
|
// Returns:
|
|
// - *DNSRecord: The found DNS record, or nil if not found
|
|
// - error: Any errors that occurred during the request
|
|
func (c *CloudflareClient) FindDNSRecord(zoneID, name, recordType string) (*DNSRecord, error) {
|
|
log.Debug("Finding DNS record with name: %s and type: %s in zone ID: %s", name, recordType, zoneID)
|
|
|
|
filter := &DNSRecordFilter{
|
|
Name: name,
|
|
Type: recordType,
|
|
}
|
|
|
|
records, err := c.ListDNSRecords(zoneID, filter)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(records) == 0 {
|
|
log.Warning("No DNS record found with name: %s and type: %s in zone ID: %s", name, recordType, zoneID)
|
|
return nil, nil
|
|
}
|
|
|
|
log.Info("Found DNS record: %s (%s) with type: %s in zone ID: %s", records[0].Name, records[0].ID, records[0].Type, zoneID)
|
|
return &records[0], nil
|
|
}
|