From 2c7203ad25ab087abb2dd0d7c83b02e53541bfec Mon Sep 17 00:00:00 2001 From: lemonlinger Date: Sat, 2 Dec 2023 21:31:02 +0800 Subject: [PATCH] add cel validation tests for health check Signed-off-by: lemonlinger --- .../backendtrafficpolicy_test.go | 230 ++++++++++++++++++ 1 file changed, 230 insertions(+) diff --git a/test/cel-validation/backendtrafficpolicy_test.go b/test/cel-validation/backendtrafficpolicy_test.go index 9ca669caea5d..bf4ed66c4d41 100644 --- a/test/cel-validation/backendtrafficpolicy_test.go +++ b/test/cel-validation/backendtrafficpolicy_test.go @@ -16,6 +16,7 @@ import ( "time" egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1" + "github.com/envoyproxy/gateway/internal/utils/ptr" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2" @@ -306,6 +307,235 @@ func TestBackendTrafficPolicyTarget(t *testing.T) { "spec.loadBalancer: Invalid value: \"object\": Currently SlowStart is only supported for RoundRobin and LeastRequest load balancers.", }, }, + { + desc: "invalid path of http health checker", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + HealthCheck: &egv1a1.HealthCheck{ + HealthChecker: egv1a1.HealthChecker{ + Type: egv1a1.HealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPHealthChecker{ + Path: "", + }, + }, + }, + } + }, + wantErrors: []string{ + `spec.healthCheck.healthChecker.http.path: Invalid value: "": spec.healthCheck.healthChecker.http.path in body should be at least 1 chars long`, + }, + }, + { + desc: "invalid unhealthy threshold", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + HealthCheck: &egv1a1.HealthCheck{ + UnhealthyThreshold: ptr.To[uint32](0), + HealthChecker: egv1a1.HealthChecker{ + Type: egv1a1.HealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPHealthChecker{ + Path: "/healthz", + }, + }, + }, + } + }, + wantErrors: []string{ + `spec.healthCheck.unhealthyThreshold: Invalid value: 0: spec.healthCheck.unhealthyThreshold in body should be greater than or equal to 1`, + }, + }, + { + desc: "invalid healthy threshold", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + HealthCheck: &egv1a1.HealthCheck{ + HealthyThreshold: ptr.To[uint32](0), + HealthChecker: egv1a1.HealthChecker{ + Type: egv1a1.HealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPHealthChecker{ + Path: "/healthz", + }, + }, + }, + } + }, + wantErrors: []string{ + `spec.healthCheck.healthyThreshold: Invalid value: 0: spec.healthCheck.healthyThreshold in body should be greater than or equal to 1`, + }, + }, + { + desc: "invalid health checker type", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + HealthCheck: &egv1a1.HealthCheck{ + HealthChecker: egv1a1.HealthChecker{ + Type: egv1a1.HealthCheckerTypeHTTP, + TCP: &egv1a1.TCPHealthChecker{}, + }, + }, + } + }, + wantErrors: []string{ + `spec.healthCheck.healthChecker: Invalid value: "object": If Health Checker type is HTTP, http field needs to be set., spec.healthCheck.healthChecker: Invalid value: "object": If Health Checker type is TCP, tcp field needs to be set`, + }, + }, + { + desc: "invalid http expected statuses", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + HealthCheck: &egv1a1.HealthCheck{ + HealthChecker: egv1a1.HealthChecker{ + Type: egv1a1.HealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPHealthChecker{ + Path: "/healthz", + ExpectedStatuses: []egv1a1.Int64Range{{Start: 400, End: 200}}, + }, + }, + }, + } + }, + wantErrors: []string{ + `spec.healthCheck.healthChecker.http.expectedStatuses[0]: Invalid value: "object": start should be not greater than end`, + }, + }, + { + desc: "invalid http expected responses", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + HealthCheck: &egv1a1.HealthCheck{ + HealthChecker: egv1a1.HealthChecker{ + Type: egv1a1.HealthCheckerTypeHTTP, + HTTP: &egv1a1.HTTPHealthChecker{ + Path: "/healthz", + ExpectedResponses: []egv1a1.HealthCheckPayload{ + { + Type: egv1a1.HealthCheckPayloadTypeText, + Binary: []byte{'f', 'o', 'o'}, + }, + { + Type: egv1a1.HealthCheckPayloadTypeBinary, + Text: ptr.To("foo"), + }, + }, + }, + }, + }, + } + }, + wantErrors: []string{ + `spec.healthCheck.healthChecker.http.expectedResponses[0]: Invalid value: "object": If payload type is Text, text field needs to be set., spec.healthCheck.healthChecker.http.expectedResponses[0]: Invalid value: "object": If payload type is Binary, binary field needs to be set., spec.healthCheck.healthChecker.http.expectedResponses[1]: Invalid value: "object": If payload type is Text, text field needs to be set., spec.healthCheck.healthChecker.http.expectedResponses[1]: Invalid value: "object": If payload type is Binary, binary field needs to be set.`, + }, + }, + { + desc: "invalid tcp send", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + HealthCheck: &egv1a1.HealthCheck{ + HealthChecker: egv1a1.HealthChecker{ + Type: egv1a1.HealthCheckerTypeTCP, + TCP: &egv1a1.TCPHealthChecker{ + Send: &egv1a1.HealthCheckPayload{ + Type: egv1a1.HealthCheckPayloadTypeText, + Binary: []byte{'f', 'o', 'o'}, + }, + Receive: []egv1a1.HealthCheckPayload{ + { + Type: egv1a1.HealthCheckPayloadTypeText, + Text: ptr.To("foo"), + }, + }, + }, + }, + }, + } + }, + wantErrors: []string{ + `spec.healthCheck.healthChecker.tcp.send: Invalid value: "object": If payload type is Text, text field needs to be set., spec.healthCheck.healthChecker.tcp.send: Invalid value: "object": If payload type is Binary, binary field needs to be set.`, + }, + }, + { + desc: "invalid tcp receive", + mutate: func(btp *egv1a1.BackendTrafficPolicy) { + btp.Spec = egv1a1.BackendTrafficPolicySpec{ + TargetRef: gwapiv1a2.PolicyTargetReferenceWithSectionName{ + PolicyTargetReference: gwapiv1a2.PolicyTargetReference{ + Group: gwapiv1a2.Group("gateway.networking.k8s.io"), + Kind: gwapiv1a2.Kind("Gateway"), + Name: gwapiv1a2.ObjectName("eg"), + }, + }, + HealthCheck: &egv1a1.HealthCheck{ + HealthChecker: egv1a1.HealthChecker{ + Type: egv1a1.HealthCheckerTypeTCP, + TCP: &egv1a1.TCPHealthChecker{ + Send: &egv1a1.HealthCheckPayload{ + Type: egv1a1.HealthCheckPayloadTypeText, + Text: ptr.To("foo"), + }, + Receive: []egv1a1.HealthCheckPayload{ + { + Type: egv1a1.HealthCheckPayloadTypeText, + Binary: []byte{'f', 'o', 'o'}, + }, + }, + }, + }, + }, + } + }, + wantErrors: []string{ + `spec.healthCheck.healthChecker.tcp.receive[0]: Invalid value: "object": If payload type is Text, text field needs to be set., spec.healthCheck.healthChecker.tcp.receive[0]: Invalid value: "object": If payload type is Binary, binary field needs to be set.`, + }, + }, } for _, tc := range cases {