Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions internal/controller/ingressclass_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,10 @@ func (r *IngressClassReconciler) processInfrastructure(tctx *provider.TranslateC
if ingressClass.Spec.Parameters.Namespace != nil {
namespace = *ingressClass.Spec.Parameters.Namespace
}
// Check for annotation override
if annotationNamespace, exists := ingressClass.Annotations[gatewayProxyNamespaceAnnotation]; exists && annotationNamespace != "" {
namespace = annotationNamespace
}

gatewayProxy := new(v1alpha1.GatewayProxy)
if err := r.Get(context.Background(), client.ObjectKey{
Expand Down
9 changes: 7 additions & 2 deletions internal/controller/ingressclass_v1beta1_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,12 +188,17 @@ func (r *IngressClassV1beta1Reconciler) processInfrastructure(tctx *provider.Tra
}

// Since v1beta1 does not support specifying the target namespace,
// and GatewayProxy is a namespace-scoped resource, we default to using
// the "default" namespace for convenience.
// and GatewayProxy is a namespace-scoped resource, we first check
// for the annotation, then fall back to the spec field, and finally
// default to "default" namespace for convenience.
namespace := "default"
if IngressClassV1beta1.Spec.Parameters.Namespace != nil {
namespace = *IngressClassV1beta1.Spec.Parameters.Namespace
}
// Check for annotation override
if annotationNamespace, exists := IngressClassV1beta1.Annotations[gatewayProxyNamespaceAnnotation]; exists && annotationNamespace != "" {
namespace = annotationNamespace
}

gatewayProxy := new(v1alpha1.GatewayProxy)
if err := r.Get(tctx, client.ObjectKey{
Expand Down
8 changes: 7 additions & 1 deletion internal/controller/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ const (
KindApisixConsumer = "ApisixConsumer"
)

const defaultIngressClassAnnotation = "ingressclass.kubernetes.io/is-default-class"
const (
defaultIngressClassAnnotation = "ingressclass.kubernetes.io/is-default-class"
gatewayProxyNamespaceAnnotation = "apisix.apache.org/gatewayproxy-namespace"
)

var (
ErrNoMatchingListenerHostname = errors.New("no matching hostnames in listener")
Expand Down Expand Up @@ -1323,6 +1326,9 @@ func ProcessIngressClassParameters(tctx *provider.TranslateContext, c client.Cli
if parameters.Namespace != nil {
ns = *parameters.Namespace
}
if annotationNamespace, exists := ingressClass.Annotations[gatewayProxyNamespaceAnnotation]; exists && annotationNamespace != "" {
ns = annotationNamespace
}

gatewayProxy := &v1alpha1.GatewayProxy{}
if err := c.Get(tctx, client.ObjectKey{
Expand Down
109 changes: 105 additions & 4 deletions test/e2e/crds/v2/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,16 @@
package v2

import (
"fmt"
"net/http"
"time"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/types"

apiv2 "github.com/apache/apisix-ingress-controller/api/v2"
"github.com/apache/apisix-ingress-controller/test/e2e/framework"
"github.com/apache/apisix-ingress-controller/test/e2e/scaffold"
)

Expand Down Expand Up @@ -56,11 +63,14 @@ spec:
`

var _ = Describe("APISIX Standalone Basic Tests", Label("apisix.apache.org", "v2", "basic"), func() {
s := scaffold.NewScaffold(&scaffold.Options{
ControllerName: "apisix.apache.org/apisix-ingress-controller",
})
var (
s = scaffold.NewScaffold(&scaffold.Options{
ControllerName: "apisix.apache.org/apisix-ingress-controller",
})
applier = framework.NewApplier(s.GinkgoT, s.K8sClient, s.CreateResourceFromString)
)

Describe("APISIX HTTP Proxy", func() {
Context("APISIX HTTP Proxy", func() {
It("should handle basic HTTP requests", func() {
httpClient := s.NewAPISIXClient()
Expect(httpClient).NotTo(BeNil())
Expand All @@ -83,6 +93,97 @@ var _ = Describe("APISIX Standalone Basic Tests", Label("apisix.apache.org", "v2
Expect().
Status(404).Body().Contains("404 Route Not Found")
})
})

Context("IngressClass Annotations", func() {
It("Basic tests", func() {
const gatewayProxyYaml = `
apiVersion: apisix.apache.org/v1alpha1
kind: GatewayProxy
metadata:
name: apisix-proxy-config
spec:
provider:
type: ControlPlane
controlPlane:
endpoints:
- %s
auth:
type: AdminKey
adminKey:
value: "%s"
`

const ingressClassYaml = `
apiVersion: networking.k8s.io/%s
kind: IngressClass
metadata:
name: apisix
annotations:
apisix.apache.org/gatewayproxy-namespace: %s
spec:
controller: apisix.apache.org/apisix-ingress-controller
parameters:
apiGroup: apisix.apache.org
kind: GatewayProxy
name: apisix-proxy-config
`

By("create GatewayProxy")
gatewayProxy := fmt.Sprintf(gatewayProxyYaml, s.Deployer.GetAdminEndpoint(), s.AdminKey())
err := s.CreateResourceFromString(gatewayProxy)
Expect(err).NotTo(HaveOccurred(), "creating GatewayProxy")
time.Sleep(5 * time.Second)

By("create IngressClass")
ingressClass := fmt.Sprintf(ingressClassYaml, framework.IngressVersion, s.Namespace())
err = s.CreateResourceFromString(ingressClass)
Expect(err).NotTo(HaveOccurred(), "creating IngressClass")
time.Sleep(5 * time.Second)

const apisixRouteSpec = `
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: default
spec:
ingressClassName: apisix
http:
- name: rule0
match:
hosts:
- httpbin
paths:
- %s
backends:
- serviceName: httpbin-service-e2e-test
servicePort: 80
`
request := func(path string) int {
return s.NewAPISIXClient().GET(path).WithHost("httpbin").Expect().Raw().StatusCode
}

By("apply ApisixRoute")
var apisixRoute apiv2.ApisixRoute
applier.MustApplyAPIv2(types.NamespacedName{Namespace: s.Namespace(), Name: "default"}, &apisixRoute, fmt.Sprintf(apisixRouteSpec, "/get"))

By("verify ApisixRoute works")
Eventually(request).WithArguments("/get").WithTimeout(8 * time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusOK))

By("update ApisixRoute")
applier.MustApplyAPIv2(types.NamespacedName{Namespace: s.Namespace(), Name: "default"}, &apisixRoute, fmt.Sprintf(apisixRouteSpec, "/headers"))
Eventually(request).WithArguments("/get").WithTimeout(8 * time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusNotFound))
s.RequestAssert(&scaffold.RequestAssert{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RequestAssert has built-in retry logic.
For consistency, we recommend using either Eventually or RequestAssert within a single test case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, i copy it from another file. we can change it in the next PR.

Method: "GET",
Path: "/headers",
Host: "httpbin",
Check: scaffold.WithExpectedStatus(http.StatusOK),
})

By("delete ApisixRoute")
err = s.DeleteResource("ApisixRoute", "default")
Expect(err).ShouldNot(HaveOccurred(), "deleting ApisixRoute")
Eventually(request).WithArguments("/headers").WithTimeout(8 * time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusNotFound))
})
})
})
3 changes: 0 additions & 3 deletions test/e2e/crds/v2/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,6 @@ spec:
Expect(bodyStr).Should(ContainSubstring("apisix_ingress_adc_sync_total"))
Expect(bodyStr).Should(ContainSubstring("apisix_ingress_status_update_queue_length"))
Expect(bodyStr).Should(ContainSubstring("apisix_ingress_file_io_duration_seconds"))

// Log metrics for debugging
fmt.Printf("Metrics endpoint response:\n%s\n", bodyStr)
})

It("Test plugins in ApisixRoute", func() {
Expand Down
Loading