From f61c8ba85641ddd2e424216f3f97b72f8547217a Mon Sep 17 00:00:00 2001 From: l1b0k Date: Wed, 4 Sep 2024 15:48:11 +0800 Subject: [PATCH] webhook: fix validate Signed-off-by: l1b0k --- pkg/controller/webhook/validate.go | 10 +- pkg/controller/webhook/validate_test.go | 198 ++++++++++++++++++++++++ 2 files changed, 202 insertions(+), 6 deletions(-) create mode 100644 pkg/controller/webhook/validate_test.go diff --git a/pkg/controller/webhook/validate.go b/pkg/controller/webhook/validate.go index 40001d4c..e152ee16 100644 --- a/pkg/controller/webhook/validate.go +++ b/pkg/controller/webhook/validate.go @@ -47,12 +47,10 @@ func ValidateHook() *webhook.Admission { return admission.Denied("security group can not more than 5") } - if podNetworking.Spec.AllocationType.ReleaseStrategy == v1beta1.IPAllocTypeFixed { - if podNetworking.Spec.AllocationType.ReleaseStrategy == v1beta1.ReleaseStrategyTTL { - _, err = time.ParseDuration(podNetworking.Spec.AllocationType.ReleaseAfter) - if err != nil { - return webhook.Denied(fmt.Sprintf("invalid releaseAfter %s", podNetworking.Spec.AllocationType.ReleaseAfter)) - } + if podNetworking.Spec.AllocationType.ReleaseStrategy == v1beta1.ReleaseStrategyTTL { + _, err = time.ParseDuration(podNetworking.Spec.AllocationType.ReleaseAfter) + if err != nil { + return webhook.Denied(fmt.Sprintf("invalid releaseAfter %s", podNetworking.Spec.AllocationType.ReleaseAfter)) } } return webhook.Allowed("checked") diff --git a/pkg/controller/webhook/validate_test.go b/pkg/controller/webhook/validate_test.go new file mode 100644 index 00000000..f6a4c0f1 --- /dev/null +++ b/pkg/controller/webhook/validate_test.go @@ -0,0 +1,198 @@ +package webhook + +import ( + "context" + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + "k8s.io/api/admission/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + + "github.com/AliyunContainerService/terway/pkg/apis/network.alibabacloud.com/v1beta1" +) + +func TestValidateHookAllowsWhenKindIsNotPodNetworking(t *testing.T) { + req := webhook.AdmissionRequest{ + AdmissionRequest: v1.AdmissionRequest{ + Kind: metav1.GroupVersionKind{ + Group: "", + Version: "", + Kind: "Foo", + }, + }, + } + resp := ValidateHook().Handle(context.Background(), req) + assert.True(t, resp.Allowed) + assert.Equal(t, "not care", resp.Result.Message) +} + +func TestValidateHookDeniesWhenPodSelectorAndNamespaceSelectorAreNil(t *testing.T) { + podNetworking := &v1beta1.PodNetworking{ + Spec: v1beta1.PodNetworkingSpec{ + Selector: v1beta1.Selector{}, + }, + } + raw, _ := json.Marshal(podNetworking) + req := webhook.AdmissionRequest{ + AdmissionRequest: v1.AdmissionRequest{ + Kind: metav1.GroupVersionKind{ + Group: "", + Version: "", + Kind: "PodNetworking", + }, + Object: runtime.RawExtension{ + Raw: raw, + }, + }, + } + resp := ValidateHook().Handle(context.Background(), req) + assert.False(t, resp.Allowed) + assert.Equal(t, "neither the PodSelector nor the NamespaceSelector is set", resp.Result.Message) +} + +func TestValidateHookDeniesWhenVSwitchOptionsIsEmpty(t *testing.T) { + podNetworking := &v1beta1.PodNetworking{ + Spec: v1beta1.PodNetworkingSpec{ + Selector: v1beta1.Selector{ + PodSelector: &metav1.LabelSelector{}, + }, + }, + } + raw, _ := json.Marshal(podNetworking) + req := webhook.AdmissionRequest{ + AdmissionRequest: v1.AdmissionRequest{ + Kind: metav1.GroupVersionKind{ + Group: "", + Version: "", + Kind: "PodNetworking", + }, + Object: runtime.RawExtension{ + Raw: raw, + }, + }, + } + resp := ValidateHook().Handle(context.Background(), req) + assert.False(t, resp.Allowed) + assert.Equal(t, "vSwitchOptions is not set", resp.Result.Message) +} + +func TestValidateHookDeniesWhenSecurityGroupIDsIsEmpty(t *testing.T) { + podNetworking := &v1beta1.PodNetworking{ + Spec: v1beta1.PodNetworkingSpec{ + Selector: v1beta1.Selector{ + PodSelector: &metav1.LabelSelector{}, + }, + VSwitchOptions: []string{"vsw-123"}, + }, + } + raw, _ := json.Marshal(podNetworking) + req := webhook.AdmissionRequest{ + AdmissionRequest: v1.AdmissionRequest{ + Kind: metav1.GroupVersionKind{ + Group: "", + Version: "", + Kind: "PodNetworking", + }, + Object: runtime.RawExtension{ + Raw: raw, + }, + }, + } + resp := ValidateHook().Handle(context.Background(), req) + assert.False(t, resp.Allowed) + assert.Equal(t, "security group is not set", resp.Result.Message) +} + +func TestValidateHookDeniesWhenSecurityGroupIDsExceedsLimit(t *testing.T) { + podNetworking := &v1beta1.PodNetworking{ + Spec: v1beta1.PodNetworkingSpec{ + Selector: v1beta1.Selector{ + PodSelector: &metav1.LabelSelector{}, + }, + VSwitchOptions: []string{"vsw-123"}, + SecurityGroupIDs: []string{"sg-1", "sg-2", "sg-3", "sg-4", "sg-5", "sg-6"}, + }, + } + raw, _ := json.Marshal(podNetworking) + req := webhook.AdmissionRequest{ + AdmissionRequest: v1.AdmissionRequest{ + Kind: metav1.GroupVersionKind{ + Group: "", + Version: "", + Kind: "PodNetworking", + }, + Object: runtime.RawExtension{ + Raw: raw, + }, + }, + } + resp := ValidateHook().Handle(context.Background(), req) + assert.False(t, resp.Allowed) + assert.Equal(t, "security group can not more than 5", resp.Result.Message) +} + +func TestValidateHookDeniesWhenReleaseAfterIsInvalid(t *testing.T) { + podNetworking := &v1beta1.PodNetworking{ + Spec: v1beta1.PodNetworkingSpec{ + Selector: v1beta1.Selector{ + PodSelector: &metav1.LabelSelector{}, + }, + VSwitchOptions: []string{"vsw-123"}, + SecurityGroupIDs: []string{"sg-1"}, + AllocationType: v1beta1.AllocationType{ + ReleaseStrategy: v1beta1.ReleaseStrategyTTL, + ReleaseAfter: "invalid-duration", + }, + }, + } + raw, _ := json.Marshal(podNetworking) + req := webhook.AdmissionRequest{ + AdmissionRequest: v1.AdmissionRequest{ + Kind: metav1.GroupVersionKind{ + Group: "", + Version: "", + Kind: "PodNetworking", + }, + Object: runtime.RawExtension{ + Raw: raw, + }, + }, + } + resp := ValidateHook().Handle(context.Background(), req) + assert.False(t, resp.Allowed) +} + +func TestValidateHookAllowsWhenAllConditionsAreMet(t *testing.T) { + podNetworking := &v1beta1.PodNetworking{ + Spec: v1beta1.PodNetworkingSpec{ + Selector: v1beta1.Selector{ + PodSelector: &metav1.LabelSelector{}, + }, + VSwitchOptions: []string{"vsw-123"}, + SecurityGroupIDs: []string{"sg-1"}, + AllocationType: v1beta1.AllocationType{ + ReleaseStrategy: v1beta1.ReleaseStrategyTTL, + ReleaseAfter: "1h", + }, + }, + } + raw, _ := json.Marshal(podNetworking) + req := webhook.AdmissionRequest{ + AdmissionRequest: v1.AdmissionRequest{ + Kind: metav1.GroupVersionKind{ + Group: "", + Version: "", + Kind: "PodNetworking", + }, + Object: runtime.RawExtension{ + Raw: raw, + }, + }, + } + resp := ValidateHook().Handle(context.Background(), req) + assert.True(t, resp.Allowed) + assert.Equal(t, "checked", resp.Result.Message) +}