chore: bump app version to v0.5.1 and enhance logging in API client and provider for better debugging
All checks were successful
Release / build-image (push) Successful in 37s
All checks were successful
Release / build-image (push) Successful in 37s
This commit is contained in:
parent
5f99618449
commit
67882bc3b6
4 changed files with 152 additions and 35 deletions
|
@ -1 +1 @@
|
|||
appVersion: v0.5.0
|
||||
appVersion: v0.5.1
|
|
@ -5,8 +5,10 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const apiURL string = "https://api.domeneshop.no/v0"
|
||||
|
@ -64,28 +66,74 @@ func NewClient(apiToken, apiSecret string) *Client {
|
|||
// Request makes a request against the API with an optional body, and makes sure
|
||||
// that the required Authorization header is set using `setBasicAuth`
|
||||
func (c *Client) Request(method string, endpoint string, reqBody []byte, v interface{}) error {
|
||||
|
||||
logLevel := strings.ToLower(os.Getenv("LOG_LEVEL"))
|
||||
var buf = bytes.NewBuffer(reqBody)
|
||||
|
||||
req, err := http.NewRequest(method, fmt.Sprintf("%s/%s", apiURL, endpoint), buf)
|
||||
fullURL := fmt.Sprintf("%s/%s", apiURL, endpoint)
|
||||
if logLevel == "debug" {
|
||||
log.Printf("Making %s request to %s", method, fullURL)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(method, fullURL, buf)
|
||||
if err != nil {
|
||||
return err
|
||||
if logLevel == "debug" {
|
||||
log.Printf("Error creating request: %v", err)
|
||||
}
|
||||
return fmt.Errorf("failed to create request: %w", err)
|
||||
}
|
||||
|
||||
// Check if credentials are provided
|
||||
if c.APIToken == "" || c.APISecret == "" {
|
||||
if logLevel == "debug" {
|
||||
log.Println("API credentials are missing or empty")
|
||||
}
|
||||
return fmt.Errorf("API token or secret is empty")
|
||||
}
|
||||
|
||||
req.SetBasicAuth(c.APIToken, c.APISecret)
|
||||
|
||||
versionInfo := version
|
||||
|
||||
req.Header.Set("User-Agent", fmt.Sprintf("external-dns-domeneshop-webhook/v"+versionInfo))
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
if len(reqBody) > 0 {
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
if logLevel == "debug" {
|
||||
log.Printf("Making request with headers: %v", req.Header)
|
||||
}
|
||||
|
||||
resp, err := c.http.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
if logLevel == "debug" {
|
||||
log.Printf("Request failed: %v", err)
|
||||
}
|
||||
return fmt.Errorf("API request failed: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBody, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
if logLevel == "debug" {
|
||||
log.Printf("Failed to read response body: %v", err)
|
||||
}
|
||||
return fmt.Errorf("failed to read response body: %w", err)
|
||||
}
|
||||
|
||||
if logLevel == "debug" {
|
||||
log.Printf("API response status: %s", resp.Status)
|
||||
if len(respBody) > 0 {
|
||||
shortBody := respBody
|
||||
if len(shortBody) > 500 {
|
||||
shortBody = shortBody[:500]
|
||||
}
|
||||
log.Printf("API response body (truncated): %s", string(shortBody))
|
||||
}
|
||||
}
|
||||
|
||||
if resp.StatusCode == 401 || resp.StatusCode == 403 {
|
||||
return fmt.Errorf("authentication failed: %s (check API token and secret)", resp.Status)
|
||||
}
|
||||
|
||||
if resp.StatusCode > 399 {
|
||||
|
@ -93,7 +141,12 @@ func (c *Client) Request(method string, endpoint string, reqBody []byte, v inter
|
|||
}
|
||||
|
||||
if v != nil {
|
||||
return json.Unmarshal(respBody, &v)
|
||||
if err := json.Unmarshal(respBody, &v); err != nil {
|
||||
if logLevel == "debug" {
|
||||
log.Printf("Failed to parse JSON response: %v", err)
|
||||
}
|
||||
return fmt.Errorf("failed to parse API response: %w", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -143,43 +196,66 @@ func (c *Client) GetDNSRecordByHostData(domain Domain, host string, data string)
|
|||
// GetDomains fetches the domain list and returns the Domain object
|
||||
// for the matching domain.
|
||||
func (c *Client) GetDomains() ([]Domain, error) {
|
||||
logLevel := strings.ToLower(os.Getenv("LOG_LEVEL"))
|
||||
var domains []Domain
|
||||
domains_list := make([]Domain, 0)
|
||||
|
||||
if logLevel == "debug" {
|
||||
log.Println("Fetching domains list from Domeneshop API")
|
||||
}
|
||||
|
||||
err := c.Request("GET", "domains", nil, &domains)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed to fetch domains: %w", err)
|
||||
}
|
||||
|
||||
if logLevel == "debug" {
|
||||
log.Printf("Retrieved %d domains from API", len(domains))
|
||||
}
|
||||
|
||||
// Filter domains to only include those with DNS service enabled
|
||||
var filteredDomains []Domain
|
||||
for _, d := range domains {
|
||||
if !d.Services.DNS {
|
||||
// Domains without DNS service cannot have DNS record added
|
||||
continue
|
||||
if d.Services.DNS {
|
||||
filteredDomains = append(filteredDomains, d)
|
||||
} else if logLevel == "debug" {
|
||||
log.Printf("Skipping domain '%s' because DNS service is not enabled", d.Name)
|
||||
}
|
||||
domains_list = append(domains_list, d)
|
||||
}
|
||||
if len(domains_list) > 0 {
|
||||
return domains_list, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("failed to find domains")
|
||||
if len(filteredDomains) == 0 {
|
||||
if logLevel == "debug" {
|
||||
log.Println("No domains with DNS service enabled were found")
|
||||
}
|
||||
return nil, fmt.Errorf("no domains with DNS service enabled found")
|
||||
}
|
||||
|
||||
if logLevel == "debug" {
|
||||
log.Printf("Returning %d domains with DNS service enabled", len(filteredDomains))
|
||||
}
|
||||
|
||||
return filteredDomains, nil
|
||||
}
|
||||
|
||||
// GetRecords fetches the records for the specified domain
|
||||
func (c *Client) GetRecords(domainId int) ([]DNSRecord, error) {
|
||||
// GetRecords fetches all DNS records for a domain
|
||||
func (c *Client) GetRecords(domainID int) ([]DNSRecord, error) {
|
||||
logLevel := strings.ToLower(os.Getenv("LOG_LEVEL"))
|
||||
var records []DNSRecord
|
||||
endpoint := "domains/" + strconv.Itoa(domainId) + "/dns"
|
||||
|
||||
if logLevel == "debug" {
|
||||
log.Printf("Fetching DNS records for domain ID %d", domainID)
|
||||
}
|
||||
|
||||
endpoint := fmt.Sprintf("domains/%d/dns", domainID)
|
||||
err := c.Request("GET", endpoint, nil, &records)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed to fetch DNS records for domain ID %d: %w", domainID, err)
|
||||
}
|
||||
|
||||
if len(records) > 0 {
|
||||
return records, nil
|
||||
if logLevel == "debug" {
|
||||
log.Printf("Retrieved %d DNS records for domain ID %d", len(records), domainID)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("failed to find records for specified domain")
|
||||
return records, nil
|
||||
}
|
||||
|
||||
func (c *Client) CreateRecord(domainZone string, record DNSRecord) bool {
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
|
@ -81,31 +82,65 @@ func (p *Provider) ApplyChanges(body io.ReadCloser) (error string) {
|
|||
}
|
||||
|
||||
func (p *Provider) Records() []*endpoint.Endpoint {
|
||||
|
||||
logLevel := strings.ToLower(os.Getenv("LOG_LEVEL"))
|
||||
endpoints := make([]*endpoint.Endpoint, 0)
|
||||
|
||||
if logLevel == "debug" {
|
||||
log.Println("Attempting to fetch domains from Domeneshop API")
|
||||
}
|
||||
|
||||
// Get all domains
|
||||
domains, err := p.domeneshopClient.GetDomains()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
if logLevel == "debug" {
|
||||
log.Printf("Error fetching domains from Domeneshop API: %v", err)
|
||||
}
|
||||
fmt.Println("failed to find domains from Domeneshop API")
|
||||
// Return empty endpoints instead of exiting
|
||||
return endpoints
|
||||
}
|
||||
|
||||
if logLevel == "debug" {
|
||||
log.Printf("Successfully fetched %d domains from Domeneshop API", len(domains))
|
||||
}
|
||||
|
||||
// Get all records for each domain
|
||||
for _, domain := range domains {
|
||||
if logLevel == "debug" {
|
||||
log.Printf("Fetching records for domain '%s' (ID: %d)", domain.Name, domain.ID)
|
||||
}
|
||||
|
||||
records, err := p.domeneshopClient.GetRecords(domain.ID)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
if logLevel == "debug" {
|
||||
log.Printf("Error fetching records for domain '%s': %v", domain.Name, err)
|
||||
}
|
||||
fmt.Printf("failed to find records for domain %s: %v\n", domain.Name, err)
|
||||
// Continue with next domain instead of exiting
|
||||
continue
|
||||
}
|
||||
|
||||
if logLevel == "debug" {
|
||||
log.Printf("Found %d records for domain '%s'", len(records), domain.Name)
|
||||
}
|
||||
|
||||
for _, record := range records {
|
||||
fqdn := record.Host + "." + domain.Name
|
||||
if logLevel == "debug" {
|
||||
log.Printf("Adding record: %s %s %s TTL:%d", fqdn, record.Type, record.Data, record.TTL)
|
||||
}
|
||||
endpoints = append(endpoints, endpoint.NewEndpointWithTTL(fqdn, record.Type, endpoint.TTL(record.TTL), record.Data))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// TODO: use SupportedRecordType in provider-package for external-dns to filter records
|
||||
|
||||
if len(endpoints) == 0 {
|
||||
fmt.Println("failed to find records for specified domain")
|
||||
if logLevel == "debug" {
|
||||
log.Println("No records found for any domains")
|
||||
}
|
||||
} else if logLevel == "debug" {
|
||||
log.Printf("Returning %d total endpoints", len(endpoints))
|
||||
}
|
||||
|
||||
return endpoints
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"sort"
|
||||
|
||||
domeneshopProvider "code.252.no/pub/external-dns-domeneshop-webhook/internal/provider"
|
||||
"sigs.k8s.io/external-dns/endpoint"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -84,14 +85,19 @@ func (p *Webhook) Records(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
records := p.provider.Records()
|
||||
if records == nil {
|
||||
// Even if there are no records, return an empty array
|
||||
records = []*endpoint.Endpoint{}
|
||||
}
|
||||
|
||||
w.Header().Set(contentTypeHeader, string(mediaTypeFormat+"version="+"1"))
|
||||
w.Header().Set(varyHeader, contentTypeHeader)
|
||||
err := json.NewEncoder(w).Encode(records)
|
||||
if err != nil {
|
||||
fmt.Printf("Error encoding JSON response: %v\n", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// This handler returns DomainFilter and is used on the route for "/""
|
||||
|
|
Loading…
Add table
Reference in a new issue