This is an automated email from the ASF dual-hosted git repository.

ronething pushed a commit to branch feat/add_resource_verify
in repository https://gitbox.apache.org/repos/asf/apisix-ingress-controller.git

commit d50dea80f26700e7b1afe484116445cdeae37bad
Author: Ashing Zheng <[email protected]>
AuthorDate: Fri Sep 26 15:31:41 2025 +0800

    fix: checker
    
    Signed-off-by: Ashing Zheng <[email protected]>
---
 internal/webhook/v1/gatewayproxy_webhook.go |  78 +++++++-------------
 internal/webhook/v1/reference/checker.go    | 107 ++++++++++++++++++++++++++++
 2 files changed, 133 insertions(+), 52 deletions(-)

diff --git a/internal/webhook/v1/gatewayproxy_webhook.go 
b/internal/webhook/v1/gatewayproxy_webhook.go
index 0abd5e34..aaa8a1de 100644
--- a/internal/webhook/v1/gatewayproxy_webhook.go
+++ b/internal/webhook/v1/gatewayproxy_webhook.go
@@ -19,9 +19,8 @@ import (
        "context"
        "fmt"
 
-       corev1 "k8s.io/api/core/v1"
-       k8serrors "k8s.io/apimachinery/pkg/api/errors"
        "k8s.io/apimachinery/pkg/runtime"
+       "k8s.io/apimachinery/pkg/types"
        ctrl "sigs.k8s.io/controller-runtime"
        "sigs.k8s.io/controller-runtime/pkg/client"
        logf "sigs.k8s.io/controller-runtime/pkg/log"
@@ -29,6 +28,7 @@ import (
        "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
 
        v1alpha1 "github.com/apache/apisix-ingress-controller/api/v1alpha1"
+       
"github.com/apache/apisix-ingress-controller/internal/webhook/v1/reference"
 )
 
 var gatewayProxyLog = logf.Log.WithName("gatewayproxy-resource")
@@ -73,61 +73,35 @@ func (v *GatewayProxyCustomValidator) 
ValidateDelete(context.Context, runtime.Ob
 }
 
 func (v *GatewayProxyCustomValidator) collectWarnings(ctx context.Context, gp 
*v1alpha1.GatewayProxy) admission.Warnings {
-       var warnings admission.Warnings
-
-       warnings = append(warnings, v.warnIfProviderServiceMissing(ctx, gp)...)
-       warnings = append(warnings, v.warnIfAdminKeySecretMissing(ctx, gp)...)
-
-       return warnings
-}
+       checker := reference.NewChecker(v.Client, gatewayProxyLog)
 
-func (v *GatewayProxyCustomValidator) warnIfProviderServiceMissing(ctx 
context.Context, gp *v1alpha1.GatewayProxy) admission.Warnings {
-       if gp.Spec.Provider == nil || gp.Spec.Provider.ControlPlane == nil || 
gp.Spec.Provider.ControlPlane.Service == nil {
-               return nil
-       }
+       var warnings admission.Warnings
 
-       svcRef := gp.Spec.Provider.ControlPlane.Service
-       key := client.ObjectKey{Namespace: gp.GetNamespace(), Name: svcRef.Name}
-       var svc corev1.Service
-       if err := v.Client.Get(ctx, key, &svc); err != nil {
-               if k8serrors.IsNotFound(err) {
-                       msg := fmt.Sprintf("Referenced Service '%s/%s' not 
found at spec.provider.controlPlane.service", key.Namespace, key.Name)
-                       gatewayProxyLog.Info("GatewayProxy references missing 
Service", "gatewayproxy", gp.GetName(), "namespace", key.Namespace, "service", 
key.Name)
-                       return admission.Warnings{msg}
+       if gp.Spec.Provider != nil && gp.Spec.Provider.ControlPlane != nil {
+               if svc := gp.Spec.Provider.ControlPlane.Service; svc != nil {
+                       warnings = append(warnings, checker.Service(ctx, 
reference.ServiceRef{
+                               Object: gp,
+                               NamespacedName: types.NamespacedName{
+                                       Namespace: gp.GetNamespace(),
+                                       Name:      svc.Name,
+                               },
+                       })...)
                }
-               gatewayProxyLog.Error(err, "failed to resolve Service for 
GatewayProxy", "gatewayproxy", gp.GetName(), "namespace", key.Namespace, 
"service", key.Name)
-       }
-       return nil
-}
-
-func (v *GatewayProxyCustomValidator) warnIfAdminKeySecretMissing(ctx 
context.Context, gp *v1alpha1.GatewayProxy) admission.Warnings {
-       if gp.Spec.Provider == nil || gp.Spec.Provider.ControlPlane == nil {
-               return nil
-       }
-
-       auth := gp.Spec.Provider.ControlPlane.Auth
-       if auth.Type != v1alpha1.AuthTypeAdminKey || auth.AdminKey == nil || 
auth.AdminKey.ValueFrom == nil || auth.AdminKey.ValueFrom.SecretKeyRef == nil {
-               return nil
-       }
 
-       ref := auth.AdminKey.ValueFrom.SecretKeyRef
-       key := client.ObjectKey{Namespace: gp.GetNamespace(), Name: ref.Name}
-       var secret corev1.Secret
-       if err := v.Client.Get(ctx, key, &secret); err != nil {
-               if k8serrors.IsNotFound(err) {
-                       msg := fmt.Sprintf("Referenced Secret '%s/%s' not found 
at spec.provider.controlPlane.auth.adminKey.valueFrom.secretKeyRef", 
key.Namespace, key.Name)
-                       gatewayProxyLog.Info("GatewayProxy references missing 
Secret", "gatewayproxy", gp.GetName(), "namespace", key.Namespace, "secret", 
key.Name)
-                       return admission.Warnings{msg}
+               auth := gp.Spec.Provider.ControlPlane.Auth
+               if auth.Type == v1alpha1.AuthTypeAdminKey && auth.AdminKey != 
nil && auth.AdminKey.ValueFrom != nil && auth.AdminKey.ValueFrom.SecretKeyRef 
!= nil {
+                       secretRef := auth.AdminKey.ValueFrom.SecretKeyRef
+                       key := secretRef.Key
+                       warnings = append(warnings, checker.Secret(ctx, 
reference.SecretRef{
+                               Object: gp,
+                               NamespacedName: types.NamespacedName{
+                                       Namespace: gp.GetNamespace(),
+                                       Name:      secretRef.Name,
+                               },
+                               Key: &key,
+                       })...)
                }
-               gatewayProxyLog.Error(err, "failed to resolve Secret for 
GatewayProxy", "gatewayproxy", gp.GetName(), "namespace", key.Namespace, 
"secret", key.Name)
-               return nil
-       }
-
-       if _, ok := secret.Data[ref.Key]; !ok {
-               msg := fmt.Sprintf("Secret key '%s' not found in Secret '%s/%s' 
at spec.provider.controlPlane.auth.adminKey.valueFrom.secretKeyRef", ref.Key, 
key.Namespace, key.Name)
-               gatewayProxyLog.Info("GatewayProxy references Secret without 
required key", "gatewayproxy", gp.GetName(), "namespace", key.Namespace, 
"secret", key.Name, "key", ref.Key)
-               return admission.Warnings{msg}
        }
 
-       return nil
+       return warnings
 }
diff --git a/internal/webhook/v1/reference/checker.go 
b/internal/webhook/v1/reference/checker.go
new file mode 100644
index 00000000..7d80c83b
--- /dev/null
+++ b/internal/webhook/v1/reference/checker.go
@@ -0,0 +1,107 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package reference
+
+import (
+       "context"
+       "fmt"
+
+       "github.com/go-logr/logr"
+       corev1 "k8s.io/api/core/v1"
+       k8serrors "k8s.io/apimachinery/pkg/api/errors"
+       "k8s.io/apimachinery/pkg/types"
+       "sigs.k8s.io/controller-runtime/pkg/client"
+       "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
+)
+
+// ServiceRef captures the information needed to validate a Service reference.
+type ServiceRef struct {
+       Object         client.Object
+       NamespacedName types.NamespacedName
+}
+
+// SecretRef captures the information needed to validate a Secret reference.
+type SecretRef struct {
+       Object         client.Object
+       NamespacedName types.NamespacedName
+       Key            *string
+}
+
+// Checker performs reference lookups and returns admission warnings on 
failure.
+type Checker struct {
+       client client.Client
+       log    logr.Logger
+}
+
+// NewChecker constructs a Checker instance.
+func NewChecker(c client.Client, log logr.Logger) Checker {
+       return Checker{client: c, log: log}
+}
+
+// Service ensures the referenced Service exists and returns warnings when it 
does not.
+func (c Checker) Service(ctx context.Context, ref ServiceRef) 
admission.Warnings {
+       if ref.NamespacedName.Name == "" || ref.NamespacedName.Namespace == "" {
+               return nil
+       }
+
+       var svc corev1.Service
+       if err := c.client.Get(ctx, ref.NamespacedName, &svc); err != nil {
+               if k8serrors.IsNotFound(err) {
+                       msg := fmt.Sprintf("Referenced Service '%s/%s' not 
found", ref.NamespacedName.Namespace, ref.NamespacedName.Name)
+                       return admission.Warnings{msg}
+               }
+               c.log.Error(err, "Failed to get Service",
+                       "ownerKind", 
ref.Object.GetObjectKind().GroupVersionKind().Kind,
+                       "ownerNamespace", ref.Object.GetNamespace(),
+                       "ownerName", ref.Object.GetName(),
+                       "serviceNamespace", ref.NamespacedName.Namespace,
+                       "serviceName", ref.NamespacedName.Name,
+               )
+       }
+       return nil
+}
+
+// Secret ensures the referenced Secret (and optional key) exists and returns 
warnings when missing.
+func (c Checker) Secret(ctx context.Context, ref SecretRef) admission.Warnings 
{
+       if ref.NamespacedName.Name == "" || ref.NamespacedName.Namespace == "" {
+               return nil
+       }
+
+       var secret corev1.Secret
+       if err := c.client.Get(ctx, ref.NamespacedName, &secret); err != nil {
+               if k8serrors.IsNotFound(err) {
+                       msg := fmt.Sprintf("Referenced Secret '%s/%s' not 
found", ref.NamespacedName.Namespace, ref.NamespacedName.Name)
+                       return admission.Warnings{msg}
+               }
+               c.log.Error(err, "Failed to get Secret",
+                       "ownerKind", 
ref.Object.GetObjectKind().GroupVersionKind().Kind,
+                       "ownerNamespace", ref.Object.GetNamespace(),
+                       "ownerName", ref.Object.GetName(),
+                       "secretNamespace", ref.NamespacedName.Namespace,
+                       "secretName", ref.NamespacedName.Name,
+               )
+               return nil
+       }
+
+       if ref.Key != nil {
+               if _, ok := secret.Data[*ref.Key]; !ok {
+                       msg := fmt.Sprintf("Secret key '%s' not found in Secret 
'%s/%s'", *ref.Key, ref.NamespacedName.Namespace, ref.NamespacedName.Name)
+                       return admission.Warnings{msg}
+               }
+       }
+
+       return nil
+}

Reply via email to