karmada/pkg/webhook/crdexplorer/validating_test.go

284 lines
7.7 KiB
Go

package crdexplorer
import (
"fmt"
"strings"
"testing"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
"k8s.io/apimachinery/pkg/util/validation/field"
configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
)
func strPtr(s string) *string { return &s }
func int32Ptr(i int32) *int32 { return &i }
func TestHasWildcardOperation(t *testing.T) {
tests := []struct {
name string
operations []configv1alpha1.OperationType
expected bool
}{
{
name: "no operations",
operations: nil,
expected: false,
},
{
name: "has wildcard operation",
operations: []configv1alpha1.OperationType{
configv1alpha1.OperationAll,
},
expected: true,
},
{
name: "no have wildcard operation",
operations: []configv1alpha1.OperationType{
configv1alpha1.ExploreReplica,
},
expected: false,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
result := hasWildcardOperation(test.operations)
if result != test.expected {
t.Errorf("Case: %s failed: expected get %v, but got %v", test.name, test.expected, result)
}
})
}
}
func TestIsAcceptedExploreReviewVersions(t *testing.T) {
tests := []struct {
name string
version string
expected bool
}{
{
name: "is accepted explore review versions",
version: acceptedExploreReviewVersions[0],
expected: true,
},
{
name: "is not accepted explore review versions",
version: "",
expected: false,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
result := isAcceptedExploreReviewVersions(test.version)
if result != test.expected {
t.Errorf("Case: %s failed: expected get %v, but got %v", test.name, test.expected, result)
}
})
}
}
func TestValidateRuleWithOperations(t *testing.T) {
fldPath := field.NewPath("webhooks").Child("rules")
notSupportedOperation := []configv1alpha1.OperationType{(configv1alpha1.OperationType)("notsupported")}
tests := []struct {
name string
ruleWithOperations *configv1alpha1.RuleWithOperations
expectedError string
}{
{
name: "no operations",
ruleWithOperations: &configv1alpha1.RuleWithOperations{},
expectedError: "operations: Required value",
},
{
name: "2 operations with wildcard",
ruleWithOperations: &configv1alpha1.RuleWithOperations{
Operations: []configv1alpha1.OperationType{
configv1alpha1.OperationAll,
configv1alpha1.ExploreReplica,
},
},
expectedError: "if '*' is present, must not specify other operations",
},
{
name: "not supported operations",
ruleWithOperations: &configv1alpha1.RuleWithOperations{Operations: notSupportedOperation},
expectedError: "operations[0]: Unsupported value",
},
{
name: "not validated rule",
ruleWithOperations: &configv1alpha1.RuleWithOperations{
Operations: []configv1alpha1.OperationType{
configv1alpha1.OperationAll,
},
Rule: configv1alpha1.Rule{
APIGroups: []string{""},
}},
expectedError: "apiVersions: Required value",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
errs := validateRuleWithOperations(test.ruleWithOperations, fldPath)
err := errs.ToAggregate()
if err != nil {
if e, a := test.expectedError, err.Error(); !strings.Contains(a, e) || e == "" {
t.Errorf("Case: %s failed: expected to contain %s, got %s", test.name, e, a)
}
} else {
if test.expectedError != "" {
t.Errorf("Case: %s failed: unexpected no error, expected to contain %s", test.name, test.expectedError)
}
}
})
}
}
func TestValidateExploreReviewVersions(t *testing.T) {
fldPath := field.NewPath("webhooks").Child("exploreReviewVersions")
tests := []struct {
name string
versions []string
expectedError string
}{
{
name: "no versions",
versions: nil,
expectedError: fmt.Sprintf("must specify one of %v", strings.Join(acceptedExploreReviewVersions, ", ")),
},
{
name: "duplicate versions",
versions: []string{"v1", "v1"},
expectedError: "duplicate version",
},
{
name: "invalid versions",
versions: []string{"test", "test"},
expectedError: fmt.Sprintf("must include at least one of %v", strings.Join(acceptedExploreReviewVersions, ", ")),
},
{
name: "invalid DNS (RFC 1035) label",
versions: []string{"a b"},
expectedError: "a DNS-1035 label must consist of lower case alphanumeric characters or '-', start with an alphabetic character, and end with an alphanumeric character",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
errs := validateExploreReviewVersions(test.versions, fldPath)
err := errs.ToAggregate()
if err != nil {
if e, a := test.expectedError, err.Error(); !strings.Contains(a, e) || e == "" {
t.Errorf("Case: %s failed: expected to contain %s, got %s", test.name, e, a)
}
} else {
if test.expectedError != "" {
t.Errorf("Case: %s failed: unexpected no error, expected to contain %s", test.name, test.expectedError)
}
}
})
}
}
func TestValidateWebhook(t *testing.T) {
fldPath := field.NewPath("webhooks")
policy := admissionregistrationv1.FailurePolicyType("fake policy")
tests := []struct {
name string
hook *configv1alpha1.ResourceExploringWebhook
expectedError string
}{
{
name: "not qualified domain name",
hook: &configv1alpha1.ResourceExploringWebhook{
Name: "",
},
expectedError: "webhooks.name: Required value",
},
{
name: "invalid rules",
hook: &configv1alpha1.ResourceExploringWebhook{
Rules: []configv1alpha1.RuleWithOperations{
{
Operations: []configv1alpha1.OperationType{},
},
},
},
expectedError: "operations: Required value",
},
{
name: "invalid policy",
hook: &configv1alpha1.ResourceExploringWebhook{
FailurePolicy: &policy,
},
expectedError: "matchPolicy",
},
{
name: "invalid timeout",
hook: &configv1alpha1.ResourceExploringWebhook{
TimeoutSeconds: int32Ptr(60),
},
expectedError: "the timeout value must be between 1 and 30 seconds",
},
{
name: "ClientConfig: exactly one of url or service is required",
hook: &configv1alpha1.ResourceExploringWebhook{
ClientConfig: admissionregistrationv1.WebhookClientConfig{},
},
expectedError: "exactly one of url or service is required",
},
{
name: "ClientConfig: invalid URL",
hook: &configv1alpha1.ResourceExploringWebhook{
ClientConfig: admissionregistrationv1.WebhookClientConfig{
URL: strPtr(""),
},
},
expectedError: "host must be provided",
},
{
name: "ClientConfig: invalid service",
hook: &configv1alpha1.ResourceExploringWebhook{
ClientConfig: admissionregistrationv1.WebhookClientConfig{
Service: &admissionregistrationv1.ServiceReference{
Name: "",
Port: int32Ptr(8080),
Path: strPtr(""),
},
},
},
expectedError: "service name is required",
},
{
name: "invalid explore review versions",
hook: &configv1alpha1.ResourceExploringWebhook{
ExploreReviewVersions: []string{""},
},
expectedError: fmt.Sprintf("must include at least one of %v", strings.Join(acceptedExploreReviewVersions, ", ")),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
errs := validateWebhook(test.hook, fldPath)
err := errs.ToAggregate()
if err != nil {
if e, a := test.expectedError, err.Error(); !strings.Contains(a, e) || e == "" {
t.Errorf("Case: %s failed: expected to contain %s, got %s", test.name, e, a)
}
} else {
if test.expectedError != "" {
t.Errorf("Case: %s failed: unexpected no error, expected to contain %s", test.name, test.expectedError)
}
}
})
}
}