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

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


The following commit(s) were added to refs/heads/master by this push:
     new 59ded942 fix: Add provider endpoints to translate context (#2442)
59ded942 is described below

commit 59ded9429670fab36b4cfba6bc4ba27e4d660670
Author: 悟空 <rainchan...@163.com>
AuthorDate: Wed Jul 2 21:31:36 2025 +0800

    fix: Add provider endpoints to translate context (#2442)
---
 api/v1alpha1/gatewayproxy_types.go                 |   6 +-
 .../bases/apisix.apache.org_gatewayproxies.yaml    |   3 +-
 internal/controller/gatewayclass_congroller.go     |   3 -
 internal/controller/ingressclass_controller.go     |  10 ++
 internal/controller/utils.go                       | 153 ++++++++++++++-------
 internal/provider/adc/config.go                    |  18 ++-
 test/e2e/gatewayapi/httproute.go                   |  30 +++-
 7 files changed, 154 insertions(+), 69 deletions(-)

diff --git a/api/v1alpha1/gatewayproxy_types.go 
b/api/v1alpha1/gatewayproxy_types.go
index 66760cdb..bf8b802a 100644
--- a/api/v1alpha1/gatewayproxy_types.go
+++ b/api/v1alpha1/gatewayproxy_types.go
@@ -22,9 +22,6 @@ import (
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
-// EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
-// NOTE: json tags are required.  Any new fields you add must have json tags 
for the fields to be serialized.
-
 // GatewayProxySpec defines the desired state of GatewayProxy.
 type GatewayProxySpec struct {
        // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
@@ -116,9 +113,10 @@ type ControlPlaneAuth struct {
 }
 
 // ControlPlaneProvider defines the configuration for control plane provider.
+// +kubebuilder:validation:XValidation:rule="has(self.endpoints) != 
has(self.service)"
 type ControlPlaneProvider struct {
        // Endpoints specifies the list of control plane endpoints.
-       // +kubebuilder:validation:Required
+       // +kubebuilder:validation:Optional
        // +kubebuilder:validation:MinItems=1
        Endpoints []string `json:"endpoints"`
 
diff --git a/config/crd/bases/apisix.apache.org_gatewayproxies.yaml 
b/config/crd/bases/apisix.apache.org_gatewayproxies.yaml
index df91df23..cd5f42c0 100644
--- a/config/crd/bases/apisix.apache.org_gatewayproxies.yaml
+++ b/config/crd/bases/apisix.apache.org_gatewayproxies.yaml
@@ -137,8 +137,9 @@ spec:
                         type: boolean
                     required:
                     - auth
-                    - endpoints
                     type: object
+                    x-kubernetes-validations:
+                    - rule: has(self.endpoints) != has(self.service)
                   type:
                     description: Type specifies the type of provider. Can only 
be
                       `ControlPlane`.
diff --git a/internal/controller/gatewayclass_congroller.go 
b/internal/controller/gatewayclass_congroller.go
index 128e5c18..ec3a7d92 100644
--- a/internal/controller/gatewayclass_congroller.go
+++ b/internal/controller/gatewayclass_congroller.go
@@ -43,9 +43,6 @@ const (
        FinalizerGatewayClassProtection = "apisix.apache.org/gc-protection"
 )
 
-// 
+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gatewayclasses,verbs=get;list;watch;update
-// 
+kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gatewayclasses/status,verbs=get;update
-
 // GatewayClassReconciler reconciles a GatewayClass object.
 type GatewayClassReconciler struct { //nolint:revive
        client.Client
diff --git a/internal/controller/ingressclass_controller.go 
b/internal/controller/ingressclass_controller.go
index c3442d52..0d71bd54 100644
--- a/internal/controller/ingressclass_controller.go
+++ b/internal/controller/ingressclass_controller.go
@@ -27,6 +27,7 @@ import (
        networkingv1 "k8s.io/api/networking/v1"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
        "k8s.io/apimachinery/pkg/runtime"
+       "k8s.io/apimachinery/pkg/types"
        ctrl "sigs.k8s.io/controller-runtime"
        "sigs.k8s.io/controller-runtime/pkg/builder"
        "sigs.k8s.io/controller-runtime/pkg/client"
@@ -229,6 +230,15 @@ func (r *IngressClassReconciler) 
processInfrastructure(tctx *provider.TranslateC
                }
        }
 
+       if service := gatewayProxy.Spec.Provider.ControlPlane.Service; service 
!= nil {
+               if err := addProviderEndpointsToTranslateContext(tctx, 
r.Client, types.NamespacedName{
+                       Namespace: gatewayProxy.GetNamespace(),
+                       Name:      service.Name,
+               }); err != nil {
+                       return err
+               }
+       }
+
        _, ok := tctx.GatewayProxies[rk]
        if !ok {
                return fmt.Errorf("no gateway proxy found for ingress class")
diff --git a/internal/controller/utils.go b/internal/controller/utils.go
index a0c3ebb0..d1049046 100644
--- a/internal/controller/utils.go
+++ b/internal/controller/utils.go
@@ -33,6 +33,7 @@ import (
        "github.com/samber/lo"
        "go.uber.org/zap"
        corev1 "k8s.io/api/core/v1"
+       discoveryv1 "k8s.io/api/discovery/v1"
        networkingv1 "k8s.io/api/networking/v1"
        "k8s.io/apimachinery/pkg/api/meta"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -921,34 +922,44 @@ func ProcessGatewayProxy(r client.Client, tctx 
*provider.TranslateContext, gatew
                        tctx.ResourceParentRefs[rk] = 
append(tctx.ResourceParentRefs[rk], gatewayKind)
 
                        // Process provider secrets if provider exists
-                       if gatewayProxy.Spec.Provider != nil && 
gatewayProxy.Spec.Provider.Type == v1alpha1.ProviderTypeControlPlane {
-                               if gatewayProxy.Spec.Provider.ControlPlane != 
nil &&
-                                       
gatewayProxy.Spec.Provider.ControlPlane.Auth.Type == v1alpha1.AuthTypeAdminKey 
&&
-                                       
gatewayProxy.Spec.Provider.ControlPlane.Auth.AdminKey != nil &&
-                                       
gatewayProxy.Spec.Provider.ControlPlane.Auth.AdminKey.ValueFrom != nil &&
-                                       
gatewayProxy.Spec.Provider.ControlPlane.Auth.AdminKey.ValueFrom.SecretKeyRef != 
nil {
-
-                                       secretRef := 
gatewayProxy.Spec.Provider.ControlPlane.Auth.AdminKey.ValueFrom.SecretKeyRef
-                                       secret := &corev1.Secret{}
-                                       if err := r.Get(context.Background(), 
client.ObjectKey{
-                                               Namespace: ns,
-                                               Name:      secretRef.Name,
-                                       }, secret); err != nil {
-                                               log.Error(err, "failed to get 
secret for GatewayProxy provider",
-                                                       "namespace", ns,
-                                                       "name", secretRef.Name)
-                                               return err
-                                       }
+                       if prov := gatewayProxy.Spec.Provider; prov != nil && 
prov.Type == v1alpha1.ProviderTypeControlPlane {
+                               if cp := prov.ControlPlane; cp != nil {
+                                       if cp.Auth.Type == 
v1alpha1.AuthTypeAdminKey &&
+                                               cp.Auth.AdminKey != nil &&
+                                               cp.Auth.AdminKey.ValueFrom != 
nil &&
+                                               
cp.Auth.AdminKey.ValueFrom.SecretKeyRef != nil {
+
+                                               secretRef := 
cp.Auth.AdminKey.ValueFrom.SecretKeyRef
+                                               secret := &corev1.Secret{}
+                                               if err := 
r.Get(context.Background(), client.ObjectKey{
+                                                       Namespace: ns,
+                                                       Name:      
secretRef.Name,
+                                               }, secret); err != nil {
+                                                       log.Error(err, "failed 
to get secret for GatewayProxy provider",
+                                                               "namespace", ns,
+                                                               "name", 
secretRef.Name)
+                                                       return err
+                                               }
 
-                                       log.Info("found secret for GatewayProxy 
provider",
-                                               "gateway", gateway.Name,
-                                               "gatewayproxy", 
gatewayProxy.Name,
-                                               "secret", secretRef.Name)
+                                               log.Info("found secret for 
GatewayProxy provider",
+                                                       "gateway", gateway.Name,
+                                                       "gatewayproxy", 
gatewayProxy.Name,
+                                                       "secret", 
secretRef.Name)
 
-                                       tctx.Secrets[k8stypes.NamespacedName{
-                                               Namespace: ns,
-                                               Name:      secretRef.Name,
-                                       }] = secret
+                                               
tctx.Secrets[k8stypes.NamespacedName{
+                                                       Namespace: ns,
+                                                       Name:      
secretRef.Name,
+                                               }] = secret
+                                       }
+
+                                       if cp.Service != nil {
+                                               if err := 
addProviderEndpointsToTranslateContext(tctx, r, k8stypes.NamespacedName{
+                                                       Namespace: 
gatewayProxy.GetNamespace(),
+                                                       Name:      
cp.Service.Name,
+                                               }); err != nil {
+                                                       return err
+                                               }
+                                       }
                                }
                        }
                }
@@ -1340,33 +1351,45 @@ func ProcessIngressClassParameters(tctx 
*provider.TranslateContext, c client.Cli
 
                // check if the provider field references a secret
                if gatewayProxy.Spec.Provider != nil && 
gatewayProxy.Spec.Provider.Type == v1alpha1.ProviderTypeControlPlane {
-                       if gatewayProxy.Spec.Provider.ControlPlane != nil &&
-                               
gatewayProxy.Spec.Provider.ControlPlane.Auth.Type == v1alpha1.AuthTypeAdminKey 
&&
-                               
gatewayProxy.Spec.Provider.ControlPlane.Auth.AdminKey != nil &&
-                               
gatewayProxy.Spec.Provider.ControlPlane.Auth.AdminKey.ValueFrom != nil &&
-                               
gatewayProxy.Spec.Provider.ControlPlane.Auth.AdminKey.ValueFrom.SecretKeyRef != 
nil {
-
-                               secretRef := 
gatewayProxy.Spec.Provider.ControlPlane.Auth.AdminKey.ValueFrom.SecretKeyRef
-                               secret := &corev1.Secret{}
-                               if err := c.Get(tctx, client.ObjectKey{
-                                       Namespace: ns,
-                                       Name:      secretRef.Name,
-                               }, secret); err != nil {
-                                       log.Error(err, "failed to get secret 
for GatewayProxy provider",
-                                               "namespace", ns,
-                                               "name", secretRef.Name)
-                                       return err
-                               }
+                       if cp := gatewayProxy.Spec.Provider.ControlPlane; cp != 
nil {
+                               // process control plane provider auth
+                               if cp.Auth.Type == v1alpha1.AuthTypeAdminKey &&
+                                       cp.Auth.AdminKey != nil &&
+                                       cp.Auth.AdminKey.ValueFrom != nil &&
+                                       cp.Auth.AdminKey.ValueFrom.SecretKeyRef 
!= nil {
+
+                                       secretRef := 
cp.Auth.AdminKey.ValueFrom.SecretKeyRef
+                                       secret := &corev1.Secret{}
+                                       if err := c.Get(tctx, client.ObjectKey{
+                                               Namespace: ns,
+                                               Name:      secretRef.Name,
+                                       }, secret); err != nil {
+                                               log.Error(err, "failed to get 
secret for GatewayProxy provider",
+                                                       "namespace", ns,
+                                                       "name", secretRef.Name)
+                                               return err
+                                       }
 
-                               log.Info("found secret for GatewayProxy 
provider",
-                                       "ingressClass", ingressClass.Name,
-                                       "gatewayproxy", gatewayProxy.Name,
-                                       "secret", secretRef.Name)
+                                       log.Info("found secret for GatewayProxy 
provider",
+                                               "ingressClass", 
ingressClass.Name,
+                                               "gatewayproxy", 
gatewayProxy.Name,
+                                               "secret", secretRef.Name)
+
+                                       tctx.Secrets[k8stypes.NamespacedName{
+                                               Namespace: ns,
+                                               Name:      secretRef.Name,
+                                       }] = secret
+                               }
 
-                               tctx.Secrets[k8stypes.NamespacedName{
-                                       Namespace: ns,
-                                       Name:      secretRef.Name,
-                               }] = secret
+                               // process control plane provider service
+                               if cp.Service != nil {
+                                       if err := 
addProviderEndpointsToTranslateContext(tctx, c, client.ObjectKey{
+                                               Namespace: 
gatewayProxy.GetNamespace(),
+                                               Name:      cp.Service.Name,
+                                       }); err != nil {
+                                               return err
+                                       }
+                               }
                        }
                }
        }
@@ -1420,3 +1443,31 @@ func distinctRequests(requests []reconcile.Request) 
[]reconcile.Request {
        }
        return distinctRequests
 }
+
+func addProviderEndpointsToTranslateContext(tctx *provider.TranslateContext, c 
client.Client, serviceNN k8stypes.NamespacedName) error {
+       log.Debugf("to process provider endpints by provider.service: %s", 
serviceNN)
+       var (
+               service corev1.Service
+       )
+       if err := c.Get(tctx, serviceNN, &service); err != nil {
+               log.Error(err, "failed to get service from GatewayProxy 
provider", "key", serviceNN)
+               return err
+       }
+       tctx.Services[serviceNN] = &service
+
+       // get es
+       var (
+               esList discoveryv1.EndpointSliceList
+       )
+       if err := c.List(tctx, &esList,
+               client.InNamespace(serviceNN.Namespace),
+               client.MatchingLabels{
+                       discoveryv1.LabelServiceName: serviceNN.Name,
+               }); err != nil {
+               log.Error(err, "failed to get endpoints for GatewayProxy 
provider", "endpoints", serviceNN)
+               return err
+       }
+       tctx.EndpointSlices[serviceNN] = esList.Items
+
+       return nil
+}
diff --git a/internal/provider/adc/config.go b/internal/provider/adc/config.go
index 6e597b78..e20c46e4 100644
--- a/internal/provider/adc/config.go
+++ b/internal/provider/adc/config.go
@@ -18,11 +18,12 @@
 package adc
 
 import (
-       "errors"
-       "fmt"
+       "net"
        "slices"
+       "strconv"
 
        "github.com/api7/gopkg/pkg/log"
+       "github.com/pkg/errors"
        "go.uber.org/zap"
        k8stypes "k8s.io/apimachinery/pkg/types"
        "k8s.io/utils/ptr"
@@ -30,7 +31,7 @@ import (
 
        "github.com/apache/apisix-ingress-controller/api/v1alpha1"
        "github.com/apache/apisix-ingress-controller/internal/provider"
-       types "github.com/apache/apisix-ingress-controller/internal/types"
+       "github.com/apache/apisix-ingress-controller/internal/types"
 )
 
 func (d *adcClient) getConfigsForGatewayProxy(tctx *provider.TranslateContext, 
gatewayProxy *v1alpha1.GatewayProxy) (*adcConfig, error) {
@@ -86,7 +87,7 @@ func (d *adcClient) getConfigsForGatewayProxy(tctx 
*provider.TranslateContext, g
                }
                _, ok := tctx.Services[namespacedName]
                if !ok {
-                       return nil, errors.New("no service found for service 
reference")
+                       return nil, errors.Errorf("no service found for service 
reference: %s", namespacedName)
                }
                endpoint := tctx.EndpointSlices[namespacedName]
                if endpoint == nil {
@@ -94,16 +95,19 @@ func (d *adcClient) getConfigsForGatewayProxy(tctx 
*provider.TranslateContext, g
                }
                upstreamNodes, err := d.translator.TranslateBackendRef(tctx, 
v1.BackendRef{
                        BackendObjectReference: v1.BackendObjectReference{
-                               Name: 
v1.ObjectName(provider.ControlPlane.Service.Name),
-                               Port: 
ptr.To(v1.PortNumber(provider.ControlPlane.Service.Port)),
+                               Name:      
v1.ObjectName(provider.ControlPlane.Service.Name),
+                               Namespace: 
(*v1.Namespace)(&gatewayProxy.Namespace),
+                               Port:      
ptr.To(v1.PortNumber(provider.ControlPlane.Service.Port)),
                        },
                })
                if err != nil {
                        return nil, err
                }
                for _, node := range upstreamNodes {
-                       config.ServerAddrs = append(config.ServerAddrs, 
fmt.Sprintf("http://%s:%d";, node.Host, node.Port))
+                       config.ServerAddrs = append(config.ServerAddrs, 
"http://"+net.JoinHostPort(node.Host, strconv.Itoa(node.Port)))
                }
+
+               log.Debugf("add server address to config.ServiceAddrs: %v", 
config.ServerAddrs)
        }
 
        return &config, nil
diff --git a/test/e2e/gatewayapi/httproute.go b/test/e2e/gatewayapi/httproute.go
index 5b9afd37..ae487e93 100644
--- a/test/e2e/gatewayapi/httproute.go
+++ b/test/e2e/gatewayapi/httproute.go
@@ -34,6 +34,7 @@ import (
        "sigs.k8s.io/gateway-api/apis/v1alpha2"
 
        "github.com/apache/apisix-ingress-controller/api/v1alpha1"
+       "github.com/apache/apisix-ingress-controller/internal/provider/adc"
        "github.com/apache/apisix-ingress-controller/test/e2e/framework"
        "github.com/apache/apisix-ingress-controller/test/e2e/scaffold"
 )
@@ -41,7 +42,28 @@ import (
 var _ = Describe("Test HTTPRoute", Label("networking.k8s.io", "httproute"), 
func() {
        s := scaffold.NewDefaultScaffold()
 
-       var gatewayProxyYaml = `
+       getGatewayProxySpec := func(endpoint, adminKey string) string {
+               if framework.ProviderType == adc.BackendModeAPISIXStandalone {
+                       var gatewayProxyYaml = `
+apiVersion: apisix.apache.org/v1alpha1
+kind: GatewayProxy
+metadata:
+  name: apisix-proxy-config
+spec:
+  provider:
+    type: ControlPlane
+    controlPlane:
+      service:
+        name: apisix-standalone
+        port: 9180
+      auth:
+        type: AdminKey
+        adminKey:
+          value: "%s"
+`
+                       return fmt.Sprintf(gatewayProxyYaml, adminKey)
+               }
+               var gatewayProxyYaml = `
 apiVersion: apisix.apache.org/v1alpha1
 kind: GatewayProxy
 metadata:
@@ -57,6 +79,8 @@ spec:
         adminKey:
           value: "%s"
 `
+               return fmt.Sprintf(gatewayProxyYaml, endpoint, adminKey)
+       }
 
        var gatewayClassYaml = `
 apiVersion: gateway.networking.k8s.io/v1
@@ -129,7 +153,7 @@ spec:
 
        var beforeEachHTTP = func() {
                By("create GatewayProxy")
-               gatewayProxy := fmt.Sprintf(gatewayProxyYaml, 
s.Deployer.GetAdminEndpoint(), s.AdminKey())
+               gatewayProxy := 
getGatewayProxySpec(s.Deployer.GetAdminEndpoint(), s.AdminKey())
                err := s.CreateResourceFromString(gatewayProxy)
                Expect(err).NotTo(HaveOccurred(), "creating GatewayProxy")
                time.Sleep(5 * time.Second)
@@ -160,7 +184,7 @@ spec:
 
        var beforeEachHTTPS = func() {
                By("create GatewayProxy")
-               gatewayProxy := fmt.Sprintf(gatewayProxyYaml, 
s.Deployer.GetAdminEndpoint(), s.AdminKey())
+               gatewayProxy := 
getGatewayProxySpec(s.Deployer.GetAdminEndpoint(), s.AdminKey())
                err := s.CreateResourceFromString(gatewayProxy)
                Expect(err).NotTo(HaveOccurred(), "creating GatewayProxy")
                time.Sleep(5 * time.Second)

Reply via email to