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: 悟空 <[email protected]>
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)