Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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[parametersNamespaceAnnotation]; 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[parametersNamespaceAnnotation]; 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"
parametersNamespaceAnnotation = "apisix.apache.org/parameters-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[parametersNamespaceAnnotation]; 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/parameters-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