add unit test for webhook validation
Signed-off-by: guoyao <1015105054@qq.com> Signed-off-by: guoyao <1015105054@qq.com>
This commit is contained in:
parent
b0742b2c9c
commit
69f990bf56
|
@ -0,0 +1,120 @@
|
|||
package crdexplorer
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
|
||||
configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
|
||||
)
|
||||
|
||||
func TestHasWildcard(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
slices []string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "TestHasWildcard(): nil input args",
|
||||
slices: nil,
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "TestHasWildcard(): has wildcard",
|
||||
slices: []string{
|
||||
"*",
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "TestHasWildcard(): not have wildcard",
|
||||
slices: []string{
|
||||
"test",
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
t.Run(testCase.name, func(t *testing.T) {
|
||||
if result := hasWildcard(testCase.slices); result != testCase.want {
|
||||
t.Errorf("Case: %s failed: want %v, but got %v", testCase.name, testCase.want, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateRule(t *testing.T) {
|
||||
fldPath := field.NewPath("webhooks")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
rule *configv1alpha1.Rule
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
name: "APIGroups required",
|
||||
rule: &configv1alpha1.Rule{},
|
||||
expectedError: "apiGroups: Required value",
|
||||
},
|
||||
{
|
||||
name: "APIGroups cannot specify both * and others",
|
||||
rule: &configv1alpha1.Rule{
|
||||
APIGroups: []string{"*", "group"},
|
||||
},
|
||||
expectedError: "if '*' is present, must not specify other API groups",
|
||||
},
|
||||
{
|
||||
name: "APIVersions required",
|
||||
rule: &configv1alpha1.Rule{},
|
||||
expectedError: "webhooks.apiVersions: Required value",
|
||||
},
|
||||
{
|
||||
name: "APIVersions cannot specify both * and others",
|
||||
rule: &configv1alpha1.Rule{
|
||||
APIVersions: []string{"*", "v1"},
|
||||
},
|
||||
expectedError: "if '*' is present, must not specify other API versions",
|
||||
},
|
||||
{
|
||||
name: "APIVersions empty is not allowed",
|
||||
rule: &configv1alpha1.Rule{
|
||||
APIVersions: []string{""},
|
||||
},
|
||||
expectedError: "apiVersions[0]: Required value",
|
||||
},
|
||||
{
|
||||
name: "Kinds required",
|
||||
rule: &configv1alpha1.Rule{},
|
||||
expectedError: "kinds: Required value",
|
||||
},
|
||||
{
|
||||
name: "Kinds cannot specify both * and others",
|
||||
rule: &configv1alpha1.Rule{
|
||||
Kinds: []string{"*", "v1"},
|
||||
},
|
||||
expectedError: "if '*' is present, must not specify other kinds",
|
||||
},
|
||||
{
|
||||
name: "Kinds empty is not allowed",
|
||||
rule: &configv1alpha1.Rule{
|
||||
Kinds: []string{""},
|
||||
},
|
||||
expectedError: "kinds[0]: Required value",
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
errs := validateRule(test.rule, 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("unexpected no error, expected to contain %s", test.expectedError)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,283 @@
|
|||
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)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue