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
|
|
}
|