- Created a comprehensive documentation file for DNS provider types, including RFC 2136, Webhook, and Script providers, detailing their use cases, configurations, and security notes. - Updated the DNSProviderForm component to handle new field types including select and textarea for better user input management. - Enhanced the DNS provider schemas to include new fields for script execution, webhook authentication, and RFC 2136 configurations, improving flexibility and usability.
857 lines
24 KiB
Go
857 lines
24 KiB
Go
package custom
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/Wikid82/charon/backend/pkg/dnsprovider"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestNewWebhookProvider(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
|
|
require.NotNil(t, provider)
|
|
assert.Equal(t, WebhookDefaultPropagationTimeout, provider.propagationTimeout)
|
|
assert.Equal(t, WebhookDefaultPollingInterval, provider.pollingInterval)
|
|
}
|
|
|
|
func TestWebhookProvider_Type(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
assert.Equal(t, "webhook", provider.Type())
|
|
}
|
|
|
|
func TestWebhookProvider_Metadata(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
metadata := provider.Metadata()
|
|
|
|
assert.Equal(t, "webhook", metadata.Type)
|
|
assert.Equal(t, "Webhook (HTTP)", metadata.Name)
|
|
assert.Contains(t, metadata.Description, "HTTP webhook")
|
|
assert.NotEmpty(t, metadata.DocumentationURL)
|
|
assert.False(t, metadata.IsBuiltIn)
|
|
assert.Equal(t, "1.0.0", metadata.Version)
|
|
assert.Equal(t, dnsprovider.InterfaceVersion, metadata.InterfaceVersion)
|
|
}
|
|
|
|
func TestWebhookProvider_Init(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
err := provider.Init()
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestWebhookProvider_Cleanup(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
err := provider.Cleanup()
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
func TestWebhookProvider_RequiredCredentialFields(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
fields := provider.RequiredCredentialFields()
|
|
|
|
expectedFields := map[string]bool{
|
|
"create_url": false,
|
|
"delete_url": false,
|
|
}
|
|
|
|
assert.Len(t, fields, len(expectedFields))
|
|
|
|
for _, field := range fields {
|
|
if _, ok := expectedFields[field.Name]; !ok {
|
|
t.Errorf("Unexpected required field: %q", field.Name)
|
|
}
|
|
expectedFields[field.Name] = true
|
|
|
|
assert.NotEmpty(t, field.Label, "Field %q has empty label", field.Name)
|
|
assert.NotEmpty(t, field.Type, "Field %q has empty type", field.Name)
|
|
assert.NotEmpty(t, field.Hint, "Field %q has empty hint", field.Name)
|
|
}
|
|
|
|
for name, found := range expectedFields {
|
|
if !found {
|
|
t.Errorf("Missing required field: %q", name)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestWebhookProvider_OptionalCredentialFields(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
fields := provider.OptionalCredentialFields()
|
|
|
|
expectedFields := map[string]bool{
|
|
"auth_header": false,
|
|
"auth_value": false,
|
|
"timeout_seconds": false,
|
|
"retry_count": false,
|
|
"insecure_skip_verify": false,
|
|
}
|
|
|
|
assert.Len(t, fields, len(expectedFields))
|
|
|
|
for _, field := range fields {
|
|
if _, ok := expectedFields[field.Name]; !ok {
|
|
t.Errorf("Unexpected optional field: %q", field.Name)
|
|
}
|
|
expectedFields[field.Name] = true
|
|
|
|
assert.NotEmpty(t, field.Label, "Field %q has empty label", field.Name)
|
|
|
|
// Verify auth_value is password type
|
|
if field.Name == "auth_value" {
|
|
assert.Equal(t, "password", field.Type, "auth_value should be password type")
|
|
}
|
|
|
|
// Verify insecure_skip_verify has select options
|
|
if field.Name == "insecure_skip_verify" {
|
|
assert.Equal(t, "select", field.Type, "insecure_skip_verify should be select type")
|
|
assert.Len(t, field.Options, 2, "insecure_skip_verify should have 2 options")
|
|
assert.Contains(t, field.Hint, "DEVELOPMENT ONLY", "insecure_skip_verify should warn about dev-only usage")
|
|
}
|
|
}
|
|
|
|
for name, found := range expectedFields {
|
|
if !found {
|
|
t.Errorf("Missing optional field: %q", name)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestWebhookProvider_ValidateCredentials(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
|
|
tests := []struct {
|
|
name string
|
|
creds map[string]string
|
|
wantErr bool
|
|
errMsg string
|
|
}{
|
|
{
|
|
name: "valid credentials with HTTPS URLs",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid credentials with localhost HTTP",
|
|
creds: map[string]string{
|
|
"create_url": "http://localhost:8080/create",
|
|
"delete_url": "http://localhost:8080/delete",
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid credentials with 127.0.0.1 HTTP",
|
|
creds: map[string]string{
|
|
"create_url": "http://127.0.0.1:8080/create",
|
|
"delete_url": "http://127.0.0.1:8080/delete",
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid credentials with all optional fields",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"auth_header": "Authorization",
|
|
"auth_value": "Bearer token123",
|
|
"timeout_seconds": "60",
|
|
"retry_count": "5",
|
|
"insecure_skip_verify": "false",
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid credentials with whitespace trimming",
|
|
creds: map[string]string{
|
|
"create_url": " https://dns-api.example.com/create ",
|
|
"delete_url": " https://dns-api.example.com/delete ",
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "missing create_url",
|
|
creds: map[string]string{
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
},
|
|
wantErr: true,
|
|
errMsg: "create_url is required",
|
|
},
|
|
{
|
|
name: "empty create_url",
|
|
creds: map[string]string{
|
|
"create_url": "",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
},
|
|
wantErr: true,
|
|
errMsg: "create_url is required",
|
|
},
|
|
{
|
|
name: "whitespace-only create_url",
|
|
creds: map[string]string{
|
|
"create_url": " ",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
},
|
|
wantErr: true,
|
|
errMsg: "create_url is required",
|
|
},
|
|
{
|
|
name: "missing delete_url",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
},
|
|
wantErr: true,
|
|
errMsg: "delete_url is required",
|
|
},
|
|
{
|
|
name: "empty delete_url",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "",
|
|
},
|
|
wantErr: true,
|
|
errMsg: "delete_url is required",
|
|
},
|
|
{
|
|
name: "invalid create_url format",
|
|
creds: map[string]string{
|
|
"create_url": "not-a-valid-url",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
},
|
|
wantErr: true,
|
|
errMsg: "create_url",
|
|
},
|
|
{
|
|
name: "create_url with ftp scheme",
|
|
creds: map[string]string{
|
|
"create_url": "ftp://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
},
|
|
wantErr: true,
|
|
errMsg: "must use http or https scheme",
|
|
},
|
|
{
|
|
name: "HTTP scheme for non-localhost",
|
|
creds: map[string]string{
|
|
"create_url": "http://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
},
|
|
wantErr: true,
|
|
errMsg: "must use HTTPS for non-localhost",
|
|
},
|
|
{
|
|
name: "timeout_seconds not a number",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"timeout_seconds": "abc",
|
|
},
|
|
wantErr: true,
|
|
errMsg: "timeout_seconds must be a number",
|
|
},
|
|
{
|
|
name: "timeout_seconds too low",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"timeout_seconds": "1",
|
|
},
|
|
wantErr: true,
|
|
errMsg: "timeout_seconds must be between",
|
|
},
|
|
{
|
|
name: "timeout_seconds too high",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"timeout_seconds": "500",
|
|
},
|
|
wantErr: true,
|
|
errMsg: "timeout_seconds must be between",
|
|
},
|
|
{
|
|
name: "retry_count not a number",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"retry_count": "abc",
|
|
},
|
|
wantErr: true,
|
|
errMsg: "retry_count must be a number",
|
|
},
|
|
{
|
|
name: "retry_count negative",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"retry_count": "-1",
|
|
},
|
|
wantErr: true,
|
|
errMsg: "retry_count must be between",
|
|
},
|
|
{
|
|
name: "retry_count too high",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"retry_count": "20",
|
|
},
|
|
wantErr: true,
|
|
errMsg: "retry_count must be between",
|
|
},
|
|
{
|
|
name: "insecure_skip_verify invalid value",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"insecure_skip_verify": "maybe",
|
|
},
|
|
wantErr: true,
|
|
errMsg: "insecure_skip_verify must be 'true' or 'false'",
|
|
},
|
|
{
|
|
name: "auth_header without auth_value",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"auth_header": "Authorization",
|
|
},
|
|
wantErr: true,
|
|
errMsg: "both auth_header and auth_value must be provided together",
|
|
},
|
|
{
|
|
name: "auth_value without auth_header",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"auth_value": "Bearer token",
|
|
},
|
|
wantErr: true,
|
|
errMsg: "both auth_header and auth_value must be provided together",
|
|
},
|
|
{
|
|
name: "valid min timeout",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"timeout_seconds": "5",
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid max timeout",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"timeout_seconds": "300",
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid min retry count",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"retry_count": "0",
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid max retry count",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"retry_count": "10",
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "insecure_skip_verify true",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"insecure_skip_verify": "true",
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "insecure_skip_verify TRUE (case insensitive)",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"insecure_skip_verify": "TRUE",
|
|
},
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "all empty credentials",
|
|
creds: map[string]string{},
|
|
wantErr: true,
|
|
errMsg: "create_url is required",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := provider.ValidateCredentials(tt.creds)
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
if tt.errMsg != "" {
|
|
assert.Contains(t, err.Error(), tt.errMsg)
|
|
}
|
|
} else {
|
|
assert.NoError(t, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWebhookProvider_ValidateWebhookURL(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
|
|
tests := []struct {
|
|
name string
|
|
url string
|
|
fieldName string
|
|
wantErr bool
|
|
errMsg string
|
|
}{
|
|
{
|
|
name: "valid HTTPS URL",
|
|
url: "https://api.example.com/webhook",
|
|
fieldName: "test_url",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid localhost HTTP",
|
|
url: "http://localhost:8080/webhook",
|
|
fieldName: "test_url",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "valid 127.0.0.1 HTTP",
|
|
url: "http://127.0.0.1:8080/webhook",
|
|
fieldName: "test_url",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "invalid scheme ftp",
|
|
url: "ftp://example.com/webhook",
|
|
fieldName: "test_url",
|
|
wantErr: true,
|
|
errMsg: "must use http or https scheme",
|
|
},
|
|
{
|
|
name: "HTTP for non-localhost rejected",
|
|
url: "http://api.example.com/webhook",
|
|
fieldName: "test_url",
|
|
wantErr: true,
|
|
errMsg: "must use HTTPS for non-localhost",
|
|
},
|
|
{
|
|
name: "missing hostname",
|
|
url: "https:///path",
|
|
fieldName: "test_url",
|
|
wantErr: true,
|
|
errMsg: "is missing hostname",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
err := provider.validateWebhookURL(tt.url, tt.fieldName)
|
|
if tt.wantErr {
|
|
assert.Error(t, err)
|
|
if tt.errMsg != "" {
|
|
assert.Contains(t, err.Error(), tt.errMsg)
|
|
}
|
|
} else {
|
|
assert.NoError(t, err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWebhookProvider_TestCredentials(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
|
|
// TestCredentials should behave the same as ValidateCredentials
|
|
validCreds := map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
}
|
|
|
|
err := provider.TestCredentials(validCreds)
|
|
assert.NoError(t, err)
|
|
|
|
invalidCreds := map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
}
|
|
|
|
err = provider.TestCredentials(invalidCreds)
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestWebhookProvider_SupportsMultiCredential(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
assert.False(t, provider.SupportsMultiCredential())
|
|
}
|
|
|
|
func TestWebhookProvider_BuildCaddyConfig(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
|
|
tests := []struct {
|
|
name string
|
|
creds map[string]string
|
|
expected map[string]any
|
|
}{
|
|
{
|
|
name: "minimal config with defaults",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
},
|
|
expected: map[string]any{
|
|
"name": "webhook",
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"timeout_seconds": WebhookDefaultTimeoutSeconds,
|
|
"retry_count": WebhookDefaultRetryCount,
|
|
"insecure_skip_verify": false,
|
|
},
|
|
},
|
|
{
|
|
name: "full config with all options",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"auth_header": "X-API-Key",
|
|
"auth_value": "secret123",
|
|
"timeout_seconds": "60",
|
|
"retry_count": "5",
|
|
"insecure_skip_verify": "true",
|
|
},
|
|
expected: map[string]any{
|
|
"name": "webhook",
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"auth_header": "X-API-Key",
|
|
"auth_value": "secret123",
|
|
"timeout_seconds": 60,
|
|
"retry_count": 5,
|
|
"insecure_skip_verify": true,
|
|
},
|
|
},
|
|
{
|
|
name: "whitespace trimming",
|
|
creds: map[string]string{
|
|
"create_url": " https://dns-api.example.com/create ",
|
|
"delete_url": " https://dns-api.example.com/delete ",
|
|
"auth_header": " Authorization ",
|
|
"auth_value": " Bearer token ",
|
|
"timeout_seconds": " 45 ",
|
|
"retry_count": " 2 ",
|
|
},
|
|
expected: map[string]any{
|
|
"name": "webhook",
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"auth_header": "Authorization",
|
|
"auth_value": "Bearer token",
|
|
"timeout_seconds": 45,
|
|
"retry_count": 2,
|
|
"insecure_skip_verify": false,
|
|
},
|
|
},
|
|
{
|
|
name: "invalid timeout falls back to default",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"timeout_seconds": "invalid",
|
|
},
|
|
expected: map[string]any{
|
|
"name": "webhook",
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"timeout_seconds": WebhookDefaultTimeoutSeconds,
|
|
"retry_count": WebhookDefaultRetryCount,
|
|
"insecure_skip_verify": false,
|
|
},
|
|
},
|
|
{
|
|
name: "out-of-range timeout falls back to default",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"timeout_seconds": "1000",
|
|
},
|
|
expected: map[string]any{
|
|
"name": "webhook",
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"timeout_seconds": WebhookDefaultTimeoutSeconds,
|
|
"retry_count": WebhookDefaultRetryCount,
|
|
"insecure_skip_verify": false,
|
|
},
|
|
},
|
|
{
|
|
name: "out-of-range retry falls back to default",
|
|
creds: map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"retry_count": "100",
|
|
},
|
|
expected: map[string]any{
|
|
"name": "webhook",
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
"timeout_seconds": WebhookDefaultTimeoutSeconds,
|
|
"retry_count": WebhookDefaultRetryCount,
|
|
"insecure_skip_verify": false,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
config := provider.BuildCaddyConfig(tt.creds)
|
|
|
|
for key, expectedValue := range tt.expected {
|
|
actualValue, ok := config[key]
|
|
if !ok {
|
|
t.Errorf("BuildCaddyConfig() missing key %q", key)
|
|
continue
|
|
}
|
|
assert.Equal(t, expectedValue, actualValue, "BuildCaddyConfig()[%q] mismatch", key)
|
|
}
|
|
|
|
// Check no unexpected keys
|
|
for key := range config {
|
|
if _, ok := tt.expected[key]; !ok {
|
|
t.Errorf("BuildCaddyConfig() unexpected key %q", key)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWebhookProvider_BuildCaddyConfigForZone(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
|
|
creds := map[string]string{
|
|
"create_url": "https://dns-api.example.com/create",
|
|
"delete_url": "https://dns-api.example.com/delete",
|
|
}
|
|
|
|
config := provider.BuildCaddyConfigForZone("example.org", creds)
|
|
|
|
// Should return same as BuildCaddyConfig since multi-credential is not supported
|
|
assert.Equal(t, "webhook", config["name"])
|
|
assert.Equal(t, "https://dns-api.example.com/create", config["create_url"])
|
|
assert.Equal(t, "https://dns-api.example.com/delete", config["delete_url"])
|
|
}
|
|
|
|
func TestWebhookProvider_PropagationTimeout(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
timeout := provider.PropagationTimeout()
|
|
|
|
assert.Equal(t, 120*time.Second, timeout)
|
|
}
|
|
|
|
func TestWebhookProvider_PollingInterval(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
interval := provider.PollingInterval()
|
|
|
|
assert.Equal(t, 5*time.Second, interval)
|
|
}
|
|
|
|
func TestWebhookProvider_GetTimeoutSeconds(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
|
|
tests := []struct {
|
|
name string
|
|
creds map[string]string
|
|
expected int
|
|
}{
|
|
{
|
|
name: "empty creds returns default",
|
|
creds: map[string]string{},
|
|
expected: WebhookDefaultTimeoutSeconds,
|
|
},
|
|
{
|
|
name: "valid timeout returns value",
|
|
creds: map[string]string{"timeout_seconds": "60"},
|
|
expected: 60,
|
|
},
|
|
{
|
|
name: "invalid number returns default",
|
|
creds: map[string]string{"timeout_seconds": "abc"},
|
|
expected: WebhookDefaultTimeoutSeconds,
|
|
},
|
|
{
|
|
name: "out of range low returns default",
|
|
creds: map[string]string{"timeout_seconds": "1"},
|
|
expected: WebhookDefaultTimeoutSeconds,
|
|
},
|
|
{
|
|
name: "out of range high returns default",
|
|
creds: map[string]string{"timeout_seconds": "500"},
|
|
expected: WebhookDefaultTimeoutSeconds,
|
|
},
|
|
{
|
|
name: "min value returns value",
|
|
creds: map[string]string{"timeout_seconds": "5"},
|
|
expected: 5,
|
|
},
|
|
{
|
|
name: "max value returns value",
|
|
creds: map[string]string{"timeout_seconds": "300"},
|
|
expected: 300,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := provider.GetTimeoutSeconds(tt.creds)
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWebhookProvider_GetRetryCount(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
|
|
tests := []struct {
|
|
name string
|
|
creds map[string]string
|
|
expected int
|
|
}{
|
|
{
|
|
name: "empty creds returns default",
|
|
creds: map[string]string{},
|
|
expected: WebhookDefaultRetryCount,
|
|
},
|
|
{
|
|
name: "valid retry count returns value",
|
|
creds: map[string]string{"retry_count": "5"},
|
|
expected: 5,
|
|
},
|
|
{
|
|
name: "invalid number returns default",
|
|
creds: map[string]string{"retry_count": "abc"},
|
|
expected: WebhookDefaultRetryCount,
|
|
},
|
|
{
|
|
name: "negative returns default",
|
|
creds: map[string]string{"retry_count": "-1"},
|
|
expected: WebhookDefaultRetryCount,
|
|
},
|
|
{
|
|
name: "out of range high returns default",
|
|
creds: map[string]string{"retry_count": "100"},
|
|
expected: WebhookDefaultRetryCount,
|
|
},
|
|
{
|
|
name: "min value returns value",
|
|
creds: map[string]string{"retry_count": "0"},
|
|
expected: 0,
|
|
},
|
|
{
|
|
name: "max value returns value",
|
|
creds: map[string]string{"retry_count": "10"},
|
|
expected: 10,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := provider.GetRetryCount(tt.creds)
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWebhookProvider_IsInsecureSkipVerify(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
|
|
tests := []struct {
|
|
name string
|
|
creds map[string]string
|
|
expected bool
|
|
}{
|
|
{
|
|
name: "empty creds returns false",
|
|
creds: map[string]string{},
|
|
expected: false,
|
|
},
|
|
{
|
|
name: "false returns false",
|
|
creds: map[string]string{"insecure_skip_verify": "false"},
|
|
expected: false,
|
|
},
|
|
{
|
|
name: "true returns true",
|
|
creds: map[string]string{"insecure_skip_verify": "true"},
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "TRUE returns true",
|
|
creds: map[string]string{"insecure_skip_verify": "TRUE"},
|
|
expected: true,
|
|
},
|
|
{
|
|
name: "False returns false",
|
|
creds: map[string]string{"insecure_skip_verify": "False"},
|
|
expected: false,
|
|
},
|
|
{
|
|
name: "invalid value returns false",
|
|
creds: map[string]string{"insecure_skip_verify": "invalid"},
|
|
expected: false,
|
|
},
|
|
{
|
|
name: "with whitespace",
|
|
creds: map[string]string{"insecure_skip_verify": " true "},
|
|
expected: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := provider.IsInsecureSkipVerify(tt.creds)
|
|
assert.Equal(t, tt.expected, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWebhookProvider_Constants(t *testing.T) {
|
|
// Verify constant values are sensible
|
|
assert.Equal(t, 30, WebhookDefaultTimeoutSeconds)
|
|
assert.Equal(t, 3, WebhookDefaultRetryCount)
|
|
assert.Equal(t, 120*time.Second, WebhookDefaultPropagationTimeout)
|
|
assert.Equal(t, 5*time.Second, WebhookDefaultPollingInterval)
|
|
assert.Equal(t, 5, WebhookMinTimeoutSeconds)
|
|
assert.Equal(t, 300, WebhookMaxTimeoutSeconds)
|
|
assert.Equal(t, 0, WebhookMinRetryCount)
|
|
assert.Equal(t, 10, WebhookMaxRetryCount)
|
|
|
|
// Ensure min < default < max for timeout
|
|
assert.Less(t, WebhookMinTimeoutSeconds, WebhookDefaultTimeoutSeconds)
|
|
assert.Less(t, WebhookDefaultTimeoutSeconds, WebhookMaxTimeoutSeconds)
|
|
|
|
// Ensure min <= default <= max for retry
|
|
assert.LessOrEqual(t, WebhookMinRetryCount, WebhookDefaultRetryCount)
|
|
assert.LessOrEqual(t, WebhookDefaultRetryCount, WebhookMaxRetryCount)
|
|
}
|
|
|
|
func TestWebhookProvider_ImplementsInterface(t *testing.T) {
|
|
provider := NewWebhookProvider()
|
|
|
|
// Compile-time check that WebhookProvider implements ProviderPlugin
|
|
var _ dnsprovider.ProviderPlugin = provider
|
|
}
|