Reviewed-on: #71 Co-authored-by: Timo Behrendt <t.behrendt@t00n.de> Co-committed-by: Timo Behrendt <t.behrendt@t00n.de>
1465 lines
38 KiB
Go
1465 lines
38 KiB
Go
package ionosDnsProvider_test
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
ionosDnsProvider "realdnydns/pkg/dnsProvider/ionos"
|
|
"testing"
|
|
)
|
|
|
|
func TestNew(t *testing.T) {
|
|
t.Run("API key is required", testNewAPIKeyIsRequired())
|
|
t.Run("Base URL is required", testNewBaseURLIsRequired())
|
|
t.Run("Valid config", testNewValidConfig())
|
|
t.Run("Valid config with custom defaults", testNewValidConfigWithCustomDefaults())
|
|
}
|
|
|
|
func testNewAPIKeyIsRequired() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
BaseURL: "https://api.ionos.com",
|
|
}
|
|
|
|
_, err := ionosDnsProvider.NewIonos(&config)
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
}
|
|
}
|
|
|
|
func testNewBaseURLIsRequired() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "1234",
|
|
}
|
|
|
|
_, err := ionosDnsProvider.NewIonos(&config)
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
}
|
|
}
|
|
|
|
func testNewValidConfig() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(200)
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "1234",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
_, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Errorf("Expected nil, got %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testNewValidConfigWithCustomDefaults() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(200)
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
customTTL := 600
|
|
customPrio := 10
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "1234",
|
|
BaseURL: mockServer.URL,
|
|
DefaultTTL: &customTTL,
|
|
DefaultPrio: &customPrio,
|
|
}
|
|
|
|
_, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Errorf("Expected nil, got %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Helper function to create a mock server that responds to IONOS API calls
|
|
func createMockServer() *httptest.Server {
|
|
zoneId := "1234567890"
|
|
recordIdSub := "abcdefghij"
|
|
recordIdTLD := "jihgfedcba"
|
|
|
|
zonesResponse := []map[string]any{
|
|
{
|
|
"name": "example.com",
|
|
"id": zoneId,
|
|
"type": "NATIVE",
|
|
},
|
|
{
|
|
"name": "notTheExample.org",
|
|
"id": "0987654321",
|
|
"type": "SLAVE",
|
|
},
|
|
}
|
|
|
|
zoneResponse := map[string]any{
|
|
"id": zoneId,
|
|
"name": "example.com",
|
|
"type": "NATIVE",
|
|
"records": []map[string]any{
|
|
{
|
|
"id": recordIdTLD,
|
|
"name": "example.com",
|
|
"rootName": "example.com",
|
|
"type": "A",
|
|
"content": "127.0.0.1",
|
|
"ttl": 300,
|
|
"prio": 0,
|
|
"disabled": false,
|
|
},
|
|
{
|
|
"id": recordIdSub,
|
|
"name": "sub.example.com",
|
|
"rootName": "example.com",
|
|
"type": "A",
|
|
"content": "127.0.0.2",
|
|
"ttl": 300,
|
|
"prio": 0,
|
|
"disabled": false,
|
|
},
|
|
},
|
|
}
|
|
|
|
recordResponseSub := map[string]any{
|
|
"id": recordIdSub,
|
|
"name": "sub.example.com",
|
|
"rootName": "example.com",
|
|
"type": "A",
|
|
"content": "127.0.0.2",
|
|
"ttl": 300,
|
|
"prio": 0,
|
|
"disabled": false,
|
|
}
|
|
|
|
recordResponseTLD := map[string]any{
|
|
"id": recordIdTLD,
|
|
"name": "example.com",
|
|
"rootName": "example.com",
|
|
"type": "A",
|
|
"content": "127.0.0.1",
|
|
"ttl": 300,
|
|
"prio": 0,
|
|
"disabled": false,
|
|
}
|
|
|
|
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
if r.Method == "GET" {
|
|
switch r.URL.Path {
|
|
case "/v1/zones":
|
|
json.NewEncoder(w).Encode(zonesResponse)
|
|
case "/v1/zones/" + zoneId:
|
|
// Check query parameters
|
|
recordName := r.URL.Query().Get("recordName")
|
|
recordType := r.URL.Query().Get("recordType")
|
|
if recordName != "" && recordType == "A" {
|
|
json.NewEncoder(w).Encode(zoneResponse)
|
|
} else {
|
|
w.WriteHeader(400)
|
|
}
|
|
case "/v1/zones/" + zoneId + "/records/" + recordIdSub:
|
|
json.NewEncoder(w).Encode(recordResponseSub)
|
|
case "/v1/zones/" + zoneId + "/records/" + recordIdTLD:
|
|
json.NewEncoder(w).Encode(recordResponseTLD)
|
|
default:
|
|
w.WriteHeader(404)
|
|
}
|
|
} else if r.Method == "PUT" {
|
|
switch r.URL.Path {
|
|
case "/v1/zones/" + zoneId + "/records/" + recordIdSub:
|
|
// Return updated record
|
|
json.NewEncoder(w).Encode(recordResponseSub)
|
|
case "/v1/zones/" + zoneId + "/records/" + recordIdTLD:
|
|
// Return updated record
|
|
json.NewEncoder(w).Encode(recordResponseTLD)
|
|
default:
|
|
w.WriteHeader(404)
|
|
}
|
|
} else {
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
}
|
|
|
|
func TestGetRecord(t *testing.T) {
|
|
t.Run("Success for subdomain", testGetRecordSuccessSubdomain())
|
|
t.Run("Success for TLD", testGetRecordSuccessTLD())
|
|
t.Run("Success for @ subdomain", testGetRecordSuccessAtSymbol())
|
|
t.Run("Error when zone not found", testGetRecordZoneNotFound())
|
|
t.Run("Error when record not found", testGetRecordRecordNotFound())
|
|
t.Run("Error when API call fails", testGetRecordAPICallFails())
|
|
t.Run("Error when record name mismatch", testGetRecordNameMismatch())
|
|
t.Run("Error when GetZonesWithResponse returns non-200", testGetRecordGetZonesWithResponseNon200())
|
|
t.Run("Error when zone id is nil", testGetRecordZoneIdNil())
|
|
t.Run("Error when zone id is empty", testGetRecordZoneIdEmpty())
|
|
t.Run("Error when GetRecordWithResponse returns non-200", testGetRecordGetRecordWithResponseNon200())
|
|
t.Run("Error when record content is nil", testGetRecordContentNil())
|
|
t.Run("Error when record content is empty", testGetRecordContentEmpty())
|
|
t.Run("Success when record ttl is nil (uses default)", testGetRecordTtlNil())
|
|
t.Run("Success when record prio is nil (uses default)", testGetRecordPrioNil())
|
|
t.Run("Success when record disabled is nil (uses default)", testGetRecordDisabledNil())
|
|
}
|
|
|
|
func testGetRecordSuccessSubdomain() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
mockServer := createMockServer()
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
record, err := provider.GetRecord("example.com", "sub")
|
|
if err != nil {
|
|
t.Errorf("Expected nil, got %v", err)
|
|
}
|
|
|
|
if record.Domain != "sub.example.com" {
|
|
t.Errorf("Expected sub.example.com, got %s", record.Domain)
|
|
}
|
|
|
|
if record.IP != "127.0.0.2" {
|
|
t.Errorf("Expected 127.0.0.2, got %s", record.IP)
|
|
}
|
|
|
|
if record.TTL != 300 {
|
|
t.Errorf("Expected 300, got %d", record.TTL)
|
|
}
|
|
|
|
if record.Prio != 0 {
|
|
t.Errorf("Expected 0, got %d", record.Prio)
|
|
}
|
|
|
|
if record.Disabled {
|
|
t.Error("Expected false, got true")
|
|
}
|
|
}
|
|
}
|
|
|
|
func testGetRecordSuccessTLD() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
mockServer := createMockServer()
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
record, err := provider.GetRecord("example.com", "")
|
|
if err != nil {
|
|
t.Errorf("Expected nil, got %v", err)
|
|
}
|
|
|
|
if record.Domain != "example.com" {
|
|
t.Errorf("Expected example.com, got %s", record.Domain)
|
|
}
|
|
|
|
if record.IP != "127.0.0.1" {
|
|
t.Errorf("Expected 127.0.0.1, got %s", record.IP)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testGetRecordSuccessAtSymbol() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
mockServer := createMockServer()
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
record, err := provider.GetRecord("example.com", "@")
|
|
if err != nil {
|
|
t.Errorf("Expected nil, got %v", err)
|
|
}
|
|
|
|
if record.Domain != "example.com" {
|
|
t.Errorf("Expected example.com, got %s", record.Domain)
|
|
}
|
|
|
|
if record.IP != "127.0.0.1" {
|
|
t.Errorf("Expected 127.0.0.1, got %s", record.IP)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testGetRecordZoneNotFound() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/v1/zones" {
|
|
json.NewEncoder(w).Encode([]map[string]any{})
|
|
} else {
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
_, err = provider.GetRecord("nonexistent.com", "sub")
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
}
|
|
}
|
|
|
|
func testGetRecordRecordNotFound() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
zoneId := "1234567890"
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
switch r.URL.Path {
|
|
case "/v1/zones":
|
|
json.NewEncoder(w).Encode([]map[string]any{
|
|
{
|
|
"name": "example.com",
|
|
"id": zoneId,
|
|
"type": "NATIVE",
|
|
},
|
|
})
|
|
case "/v1/zones/" + zoneId:
|
|
zoneResponse := map[string]any{
|
|
"id": zoneId,
|
|
"name": "example.com",
|
|
"type": "NATIVE",
|
|
"records": []map[string]any{},
|
|
}
|
|
json.NewEncoder(w).Encode(zoneResponse)
|
|
default:
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
_, err = provider.GetRecord("example.com", "nonexistent")
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
}
|
|
}
|
|
|
|
func testGetRecordAPICallFails() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(500)
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
_, err = provider.GetRecord("example.com", "sub")
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
}
|
|
}
|
|
|
|
func testGetRecordNameMismatch() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
zoneId := "1234567890"
|
|
recordId := "abcdefghij"
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
switch r.URL.Path {
|
|
case "/v1/zones":
|
|
json.NewEncoder(w).Encode([]map[string]any{
|
|
{
|
|
"name": "example.com",
|
|
"id": zoneId,
|
|
"type": "NATIVE",
|
|
},
|
|
})
|
|
case "/v1/zones/" + zoneId:
|
|
zoneResponse := map[string]any{
|
|
"id": zoneId,
|
|
"name": "example.com",
|
|
"type": "NATIVE",
|
|
"records": []map[string]any{
|
|
{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"type": "A",
|
|
},
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(zoneResponse)
|
|
case "/v1/zones/" + zoneId + "/records/" + recordId:
|
|
// Return record with wrong name
|
|
recordResponse := map[string]any{
|
|
"id": recordId,
|
|
"name": "wrong.example.com",
|
|
"rootName": "example.com",
|
|
"type": "A",
|
|
"content": "127.0.0.1",
|
|
"ttl": 300,
|
|
"prio": 0,
|
|
"disabled": false,
|
|
}
|
|
json.NewEncoder(w).Encode(recordResponse)
|
|
default:
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
_, err = provider.GetRecord("example.com", "sub")
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
}
|
|
}
|
|
|
|
func testGetRecordGetZonesWithResponseNon200() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path == "/v1/zones" {
|
|
w.WriteHeader(401) // Unauthorized
|
|
} else {
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
_, err = provider.GetRecord("example.com", "sub")
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
if err.Error() != "failed to get zones" {
|
|
t.Errorf("Expected 'failed to get zones', got %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testGetRecordZoneIdNil() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/v1/zones" {
|
|
// Return zone with nil id
|
|
zonesResponse := []map[string]any{
|
|
{
|
|
"name": "example.com",
|
|
"id": nil,
|
|
"type": "NATIVE",
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(zonesResponse)
|
|
} else {
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
_, err = provider.GetRecord("example.com", "sub")
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
if err.Error() != "zone id is empty" {
|
|
t.Errorf("Expected 'zone id is empty', got %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testGetRecordZoneIdEmpty() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/v1/zones" {
|
|
// Return zone with empty id
|
|
zonesResponse := []map[string]any{
|
|
{
|
|
"name": "example.com",
|
|
"id": "",
|
|
"type": "NATIVE",
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(zonesResponse)
|
|
} else {
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
_, err = provider.GetRecord("example.com", "sub")
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
if err.Error() != "zone id is empty" {
|
|
t.Errorf("Expected 'zone id is empty', got %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testGetRecordGetRecordWithResponseNon200() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
zoneId := "1234567890"
|
|
recordId := "abcdefghij"
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
switch r.URL.Path {
|
|
case "/v1/zones":
|
|
json.NewEncoder(w).Encode([]map[string]any{
|
|
{
|
|
"name": "example.com",
|
|
"id": zoneId,
|
|
"type": "NATIVE",
|
|
},
|
|
})
|
|
case "/v1/zones/" + zoneId:
|
|
zoneResponse := map[string]any{
|
|
"id": zoneId,
|
|
"name": "example.com",
|
|
"type": "NATIVE",
|
|
"records": []map[string]any{
|
|
{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"type": "A",
|
|
},
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(zoneResponse)
|
|
case "/v1/zones/" + zoneId + "/records/" + recordId:
|
|
// Return non-200 status
|
|
w.WriteHeader(500)
|
|
default:
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
_, err = provider.GetRecord("example.com", "sub")
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
if err.Error() != "failed to get record" {
|
|
t.Errorf("Expected 'failed to get record', got %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testGetRecordContentNil() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
zoneId := "1234567890"
|
|
recordId := "abcdefghij"
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
switch {
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones":
|
|
json.NewEncoder(w).Encode([]map[string]any{
|
|
{
|
|
"name": "example.com",
|
|
"id": zoneId,
|
|
"type": "NATIVE",
|
|
},
|
|
})
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones/"+zoneId:
|
|
zoneResponse := map[string]any{
|
|
"id": zoneId,
|
|
"name": "example.com",
|
|
"type": "NATIVE",
|
|
"records": []map[string]any{
|
|
{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"type": "A",
|
|
},
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(zoneResponse)
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones/"+zoneId+"/records/"+recordId:
|
|
recordResponse := map[string]any{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"rootName": "example.com",
|
|
"type": "A",
|
|
"content": nil,
|
|
"ttl": 300,
|
|
"prio": 0,
|
|
"disabled": false,
|
|
}
|
|
json.NewEncoder(w).Encode(recordResponse)
|
|
default:
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
_, err = provider.GetRecord("example.com", "sub")
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
if err.Error() != "record content is empty" {
|
|
t.Errorf("Expected 'record content is empty', got %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testGetRecordContentEmpty() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
zoneId := "1234567890"
|
|
recordId := "abcdefghij"
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
switch {
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones":
|
|
json.NewEncoder(w).Encode([]map[string]any{
|
|
{
|
|
"name": "example.com",
|
|
"id": zoneId,
|
|
"type": "NATIVE",
|
|
},
|
|
})
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones/"+zoneId:
|
|
zoneResponse := map[string]any{
|
|
"id": zoneId,
|
|
"name": "example.com",
|
|
"type": "NATIVE",
|
|
"records": []map[string]any{
|
|
{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"type": "A",
|
|
},
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(zoneResponse)
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones/"+zoneId+"/records/"+recordId:
|
|
recordResponse := map[string]any{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"rootName": "example.com",
|
|
"type": "A",
|
|
"content": "",
|
|
"ttl": 300,
|
|
"prio": 0,
|
|
"disabled": false,
|
|
}
|
|
json.NewEncoder(w).Encode(recordResponse)
|
|
default:
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
_, err = provider.GetRecord("example.com", "sub")
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
if err.Error() != "record content is empty" {
|
|
t.Errorf("Expected 'record content is empty', got %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testGetRecordTtlNil() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
zoneId := "1234567890"
|
|
recordId := "abcdefghij"
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
switch {
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones":
|
|
json.NewEncoder(w).Encode([]map[string]any{
|
|
{
|
|
"name": "example.com",
|
|
"id": zoneId,
|
|
"type": "NATIVE",
|
|
},
|
|
})
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones/"+zoneId:
|
|
zoneResponse := map[string]any{
|
|
"id": zoneId,
|
|
"name": "example.com",
|
|
"type": "NATIVE",
|
|
"records": []map[string]any{
|
|
{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"type": "A",
|
|
},
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(zoneResponse)
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones/"+zoneId+"/records/"+recordId:
|
|
recordResponse := map[string]any{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"rootName": "example.com",
|
|
"type": "A",
|
|
"content": "127.0.0.1",
|
|
"ttl": nil,
|
|
"prio": 0,
|
|
"disabled": false,
|
|
}
|
|
json.NewEncoder(w).Encode(recordResponse)
|
|
case r.Method == "PUT" && r.URL.Path == "/v1/zones/"+zoneId+"/records/"+recordId:
|
|
// Return updated record with TTL set
|
|
recordResponse := map[string]any{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"rootName": "example.com",
|
|
"type": "A",
|
|
"content": "127.0.0.1",
|
|
"ttl": 300,
|
|
"prio": 0,
|
|
"disabled": false,
|
|
}
|
|
json.NewEncoder(w).Encode(recordResponse)
|
|
default:
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
record, err := provider.GetRecord("example.com", "sub")
|
|
if err != nil {
|
|
t.Errorf("Expected nil, got %v", err)
|
|
}
|
|
if record.TTL != 300 {
|
|
t.Errorf("Expected TTL to be 300 (default after patch), got %d", record.TTL)
|
|
}
|
|
if record.IP != "127.0.0.1" {
|
|
t.Errorf("Expected IP to be 127.0.0.1, got %s", record.IP)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testGetRecordPrioNil() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
zoneId := "1234567890"
|
|
recordId := "abcdefghij"
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
switch {
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones":
|
|
json.NewEncoder(w).Encode([]map[string]any{
|
|
{
|
|
"name": "example.com",
|
|
"id": zoneId,
|
|
"type": "NATIVE",
|
|
},
|
|
})
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones/"+zoneId:
|
|
zoneResponse := map[string]any{
|
|
"id": zoneId,
|
|
"name": "example.com",
|
|
"type": "NATIVE",
|
|
"records": []map[string]any{
|
|
{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"type": "A",
|
|
},
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(zoneResponse)
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones/"+zoneId+"/records/"+recordId:
|
|
recordResponse := map[string]any{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"rootName": "example.com",
|
|
"type": "A",
|
|
"content": "127.0.0.1",
|
|
"ttl": 300,
|
|
"prio": nil,
|
|
"disabled": false,
|
|
}
|
|
json.NewEncoder(w).Encode(recordResponse)
|
|
case r.Method == "PUT" && r.URL.Path == "/v1/zones/"+zoneId+"/records/"+recordId:
|
|
// Return updated record with Prio set
|
|
recordResponse := map[string]any{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"rootName": "example.com",
|
|
"type": "A",
|
|
"content": "127.0.0.1",
|
|
"ttl": 300,
|
|
"prio": 0,
|
|
"disabled": false,
|
|
}
|
|
json.NewEncoder(w).Encode(recordResponse)
|
|
default:
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
record, err := provider.GetRecord("example.com", "sub")
|
|
if err != nil {
|
|
t.Errorf("Expected nil, got %v", err)
|
|
}
|
|
if record.Prio != 0 {
|
|
t.Errorf("Expected Prio to be 0 (default after patch), got %d", record.Prio)
|
|
}
|
|
if record.IP != "127.0.0.1" {
|
|
t.Errorf("Expected IP to be 127.0.0.1, got %s", record.IP)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testGetRecordDisabledNil() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
zoneId := "1234567890"
|
|
recordId := "abcdefghij"
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
switch {
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones":
|
|
json.NewEncoder(w).Encode([]map[string]any{
|
|
{
|
|
"name": "example.com",
|
|
"id": zoneId,
|
|
"type": "NATIVE",
|
|
},
|
|
})
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones/"+zoneId:
|
|
zoneResponse := map[string]any{
|
|
"id": zoneId,
|
|
"name": "example.com",
|
|
"type": "NATIVE",
|
|
"records": []map[string]any{
|
|
{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"type": "A",
|
|
},
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(zoneResponse)
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones/"+zoneId+"/records/"+recordId:
|
|
recordResponse := map[string]any{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"rootName": "example.com",
|
|
"type": "A",
|
|
"content": "127.0.0.1",
|
|
"ttl": 300,
|
|
"prio": 0,
|
|
"disabled": nil,
|
|
}
|
|
json.NewEncoder(w).Encode(recordResponse)
|
|
case r.Method == "PUT" && r.URL.Path == "/v1/zones/"+zoneId+"/records/"+recordId:
|
|
// Return updated record with Disabled set
|
|
recordResponse := map[string]any{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"rootName": "example.com",
|
|
"type": "A",
|
|
"content": "127.0.0.1",
|
|
"ttl": 300,
|
|
"prio": 0,
|
|
"disabled": false,
|
|
}
|
|
json.NewEncoder(w).Encode(recordResponse)
|
|
default:
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
record, err := provider.GetRecord("example.com", "sub")
|
|
if err != nil {
|
|
t.Errorf("Expected nil, got %v", err)
|
|
}
|
|
if record.Disabled != false {
|
|
t.Errorf("Expected Disabled to be false (default after patch), got %v", record.Disabled)
|
|
}
|
|
if record.IP != "127.0.0.1" {
|
|
t.Errorf("Expected IP to be 127.0.0.1, got %s", record.IP)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestUpdateRecord(t *testing.T) {
|
|
t.Run("Success for subdomain", testUpdateRecordSuccessSubdomain())
|
|
t.Run("Success for TLD", testUpdateRecordSuccessTLD())
|
|
t.Run("Error when zone not found", testUpdateRecordZoneNotFound())
|
|
t.Run("Error when record not found", testUpdateRecordRecordNotFound())
|
|
t.Run("Error when UpdateRecordWithResponse returns non-200", testUpdateRecordAPICallFails())
|
|
t.Run("Error when record response is empty", testUpdateRecordEmptyResponse())
|
|
}
|
|
|
|
func testUpdateRecordSuccessSubdomain() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
zoneId := "1234567890"
|
|
recordId := "abcdefghij"
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
switch {
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones":
|
|
json.NewEncoder(w).Encode([]map[string]any{
|
|
{
|
|
"name": "example.com",
|
|
"id": zoneId,
|
|
"type": "NATIVE",
|
|
},
|
|
})
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones/"+zoneId:
|
|
recordName := r.URL.Query().Get("recordName")
|
|
if recordName == "sub.example.com" {
|
|
zoneResponse := map[string]any{
|
|
"id": zoneId,
|
|
"name": "example.com",
|
|
"type": "NATIVE",
|
|
"records": []map[string]any{
|
|
{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"type": "A",
|
|
},
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(zoneResponse)
|
|
} else {
|
|
w.WriteHeader(400)
|
|
}
|
|
case r.Method == "PUT" && r.URL.Path == "/v1/zones/"+zoneId+"/records/"+recordId:
|
|
recordResponse := map[string]any{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"rootName": "example.com",
|
|
"type": "A",
|
|
"content": "192.168.1.1",
|
|
"ttl": 60,
|
|
"prio": 0,
|
|
"disabled": false,
|
|
}
|
|
json.NewEncoder(w).Encode(recordResponse)
|
|
default:
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
record, err := provider.UpdateRecord("example.com", "sub", net.ParseIP("192.168.1.1"), 60, 0, false)
|
|
if err != nil {
|
|
t.Errorf("Expected nil, got %v", err)
|
|
}
|
|
|
|
if record.Domain != "sub.example.com" {
|
|
t.Errorf("Expected sub.example.com, got %s", record.Domain)
|
|
}
|
|
|
|
if record.IP != "192.168.1.1" {
|
|
t.Errorf("Expected 192.168.1.1, got %s", record.IP)
|
|
}
|
|
|
|
if record.TTL != 60 {
|
|
t.Errorf("Expected 60, got %d", record.TTL)
|
|
}
|
|
|
|
if record.Prio != 0 {
|
|
t.Errorf("Expected 0, got %d", record.Prio)
|
|
}
|
|
|
|
if record.Disabled {
|
|
t.Error("Expected false, got true")
|
|
}
|
|
}
|
|
}
|
|
|
|
func testUpdateRecordSuccessTLD() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
zoneId := "1234567890"
|
|
recordId := "jihgfedcba"
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
switch {
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones":
|
|
json.NewEncoder(w).Encode([]map[string]any{
|
|
{
|
|
"name": "example.com",
|
|
"id": zoneId,
|
|
"type": "NATIVE",
|
|
},
|
|
})
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones/"+zoneId:
|
|
recordName := r.URL.Query().Get("recordName")
|
|
if recordName == "example.com" {
|
|
zoneResponse := map[string]any{
|
|
"id": zoneId,
|
|
"name": "example.com",
|
|
"type": "NATIVE",
|
|
"records": []map[string]any{
|
|
{
|
|
"id": recordId,
|
|
"name": "example.com",
|
|
"type": "A",
|
|
},
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(zoneResponse)
|
|
} else {
|
|
w.WriteHeader(400)
|
|
}
|
|
case r.Method == "PUT" && r.URL.Path == "/v1/zones/"+zoneId+"/records/"+recordId:
|
|
recordResponse := map[string]any{
|
|
"id": recordId,
|
|
"name": "example.com",
|
|
"rootName": "example.com",
|
|
"type": "A",
|
|
"content": "192.168.1.1",
|
|
"ttl": 300,
|
|
"prio": 0,
|
|
"disabled": false,
|
|
}
|
|
json.NewEncoder(w).Encode(recordResponse)
|
|
default:
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
record, err := provider.UpdateRecord("example.com", "", net.ParseIP("192.168.1.1"), 300, 0, false)
|
|
if err != nil {
|
|
t.Errorf("Expected nil, got %v", err)
|
|
}
|
|
|
|
if record.Domain != "example.com" {
|
|
t.Errorf("Expected example.com, got %s", record.Domain)
|
|
}
|
|
|
|
if record.IP != "192.168.1.1" {
|
|
t.Errorf("Expected 192.168.1.1, got %s", record.IP)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testUpdateRecordZoneNotFound() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/v1/zones" {
|
|
json.NewEncoder(w).Encode([]map[string]any{})
|
|
} else {
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
_, err = provider.UpdateRecord("nonexistent.com", "sub", net.ParseIP("192.168.1.1"), 60, 0, false)
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
}
|
|
}
|
|
|
|
func testUpdateRecordRecordNotFound() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
zoneId := "1234567890"
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
switch {
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones":
|
|
json.NewEncoder(w).Encode([]map[string]any{
|
|
{
|
|
"name": "example.com",
|
|
"id": zoneId,
|
|
"type": "NATIVE",
|
|
},
|
|
})
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones/"+zoneId:
|
|
zoneResponse := map[string]any{
|
|
"id": zoneId,
|
|
"name": "example.com",
|
|
"type": "NATIVE",
|
|
"records": []map[string]any{},
|
|
}
|
|
json.NewEncoder(w).Encode(zoneResponse)
|
|
default:
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
_, err = provider.UpdateRecord("example.com", "nonexistent", net.ParseIP("192.168.1.1"), 60, 0, false)
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
}
|
|
}
|
|
|
|
func testUpdateRecordAPICallFails() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
zoneId := "1234567890"
|
|
recordId := "abcdefghij"
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
switch {
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones":
|
|
json.NewEncoder(w).Encode([]map[string]any{
|
|
{
|
|
"name": "example.com",
|
|
"id": zoneId,
|
|
"type": "NATIVE",
|
|
},
|
|
})
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones/"+zoneId:
|
|
recordName := r.URL.Query().Get("recordName")
|
|
if recordName == "sub.example.com" {
|
|
zoneResponse := map[string]any{
|
|
"id": zoneId,
|
|
"name": "example.com",
|
|
"type": "NATIVE",
|
|
"records": []map[string]any{
|
|
{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"type": "A",
|
|
},
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(zoneResponse)
|
|
} else {
|
|
w.WriteHeader(400)
|
|
}
|
|
case r.Method == "PUT" && r.URL.Path == "/v1/zones/"+zoneId+"/records/"+recordId:
|
|
w.WriteHeader(500)
|
|
default:
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
_, err = provider.UpdateRecord("example.com", "sub", net.ParseIP("192.168.1.1"), 60, 0, false)
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
if err.Error() != "failed to update record" {
|
|
t.Errorf("Expected 'failed to update record', got %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func testUpdateRecordEmptyResponse() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
zoneId := "1234567890"
|
|
recordId := "abcdefghij"
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
switch {
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones":
|
|
json.NewEncoder(w).Encode([]map[string]any{
|
|
{
|
|
"name": "example.com",
|
|
"id": zoneId,
|
|
"type": "NATIVE",
|
|
},
|
|
})
|
|
case r.Method == "GET" && r.URL.Path == "/v1/zones/"+zoneId:
|
|
recordName := r.URL.Query().Get("recordName")
|
|
if recordName == "sub.example.com" {
|
|
zoneResponse := map[string]any{
|
|
"id": zoneId,
|
|
"name": "example.com",
|
|
"type": "NATIVE",
|
|
"records": []map[string]any{
|
|
{
|
|
"id": recordId,
|
|
"name": "sub.example.com",
|
|
"type": "A",
|
|
},
|
|
},
|
|
}
|
|
json.NewEncoder(w).Encode(zoneResponse)
|
|
} else {
|
|
w.WriteHeader(400)
|
|
}
|
|
case r.Method == "PUT" && r.URL.Path == "/v1/zones/"+zoneId+"/records/"+recordId:
|
|
// Return record with nil fields
|
|
recordResponse := map[string]any{
|
|
"id": recordId,
|
|
"name": nil,
|
|
"rootName": "example.com",
|
|
"type": "A",
|
|
"content": nil,
|
|
"ttl": nil,
|
|
"prio": nil,
|
|
"disabled": nil,
|
|
}
|
|
json.NewEncoder(w).Encode(recordResponse)
|
|
default:
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
_, err = provider.UpdateRecord("example.com", "sub", net.ParseIP("192.168.1.1"), 60, 0, false)
|
|
if err == nil {
|
|
t.Error("Expected error, got nil")
|
|
}
|
|
if err.Error() != "record is empty" {
|
|
t.Errorf("Expected 'record is empty', got %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGetZoneIdCaching(t *testing.T) {
|
|
t.Run("Zone ID is cached", testGetZoneIdCaching())
|
|
}
|
|
|
|
func testGetZoneIdCaching() func(*testing.T) {
|
|
return func(t *testing.T) {
|
|
callCount := 0
|
|
zoneId := "1234567890"
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if r.URL.Path == "/v1/zones" {
|
|
callCount++
|
|
json.NewEncoder(w).Encode([]map[string]any{
|
|
{
|
|
"name": "example.com",
|
|
"id": zoneId,
|
|
"type": "NATIVE",
|
|
},
|
|
})
|
|
} else {
|
|
w.WriteHeader(404)
|
|
}
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
config := ionosDnsProvider.IONOSConfig{
|
|
APIKey: "test-key",
|
|
BaseURL: mockServer.URL,
|
|
}
|
|
|
|
provider, err := ionosDnsProvider.NewIonos(&config)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create provider: %v", err)
|
|
}
|
|
|
|
// First call should fetch from API
|
|
_, err = provider.GetRecord("example.com", "sub")
|
|
if err == nil {
|
|
// Second call should use cached zone ID
|
|
_, err = provider.GetRecord("example.com", "")
|
|
if err == nil {
|
|
// The API should only be called once for zones
|
|
if callCount > 1 {
|
|
t.Errorf("Expected zone API to be called once, but was called %d times", callCount)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|