You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by al...@apache.org on 2023/03/22 03:49:44 UTC

[apisix-ingress-controller] branch master updated: feat: support ingressClass for ApisixGlobalRule (#1718)

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

alinsran 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 6e22838d feat: support ingressClass for ApisixGlobalRule (#1718)
6e22838d is described below

commit 6e22838d6f67785f69c5f8e2eb66ce02ee45a7a3
Author: Sarasa Kisaragi <li...@gmail.com>
AuthorDate: Wed Mar 22 11:49:39 2023 +0800

    feat: support ingressClass for ApisixGlobalRule (#1718)
    
    Signed-off-by: Ling Samuel <li...@gmail.com>
---
 pkg/kube/apisix/apis/config/v2/types.go            |   4 +
 pkg/providers/apisix/apisix_global_rule.go         |  34 ++++-
 samples/deploy/crd/v1/ApisixGlobalRule.yaml        |   2 +
 .../suite-ingress-features/ingress-class.go        | 139 +++++++++++++++++++++
 4 files changed, 176 insertions(+), 3 deletions(-)

diff --git a/pkg/kube/apisix/apis/config/v2/types.go b/pkg/kube/apisix/apis/config/v2/types.go
index 0b2c0626..b016d6c3 100644
--- a/pkg/kube/apisix/apis/config/v2/types.go
+++ b/pkg/kube/apisix/apis/config/v2/types.go
@@ -829,6 +829,10 @@ type ApisixGlobalRule struct {
 
 // ApisixGlobalRuleSpec defines the desired state of ApisixGlobalRuleSpec.
 type ApisixGlobalRuleSpec struct {
+	// IngressClassName is the name of an IngressClass cluster resource.
+	// The controller uses this field to decide whether the resource should be managed or not.
+	// +optional
+	IngressClassName string `json:"ingressClassName,omitempty" yaml:"ingressClassName,omitempty"`
 	// Plugins contains a list of ApisixRoutePlugin
 	// +required
 	Plugins []ApisixRoutePlugin `json:"plugins" yaml:"plugins"`
diff --git a/pkg/providers/apisix/apisix_global_rule.go b/pkg/providers/apisix/apisix_global_rule.go
index c15d3e83..9ebbb66f 100644
--- a/pkg/providers/apisix/apisix_global_rule.go
+++ b/pkg/providers/apisix/apisix_global_rule.go
@@ -244,13 +244,15 @@ func (c *apisixGlobalRuleController) onAdd(obj interface{}) {
 		log.Errorf("found ApisixGlobalRule resource with bad meta namespace key: %s", err)
 		return
 	}
+	agr := kube.MustNewApisixGlobalRule(obj)
+	if !c.isEffective(agr) {
+		return
+	}
 	if !c.namespaceProvider.IsWatchingNamespace(key) {
 		return
 	}
 	log.Debugw("ApisixGlobalRule add event arrived",
 		zap.Any("object", obj))
-
-	agr := kube.MustNewApisixGlobalRule(obj)
 	c.workqueue.Add(&types.Event{
 		Type: types.EventAdd,
 		Object: kube.ApisixGlobalRuleEvent{
@@ -273,6 +275,9 @@ func (c *apisixGlobalRuleController) onUpdate(oldObj, newObj interface{}) {
 		log.Errorf("found ApisixGlobalRule resource with bad meta namespace key: %s", err)
 		return
 	}
+	if !c.isEffective(curr) {
+		return
+	}
 	if !c.namespaceProvider.IsWatchingNamespace(key) {
 		return
 	}
@@ -306,6 +311,9 @@ func (c *apisixGlobalRuleController) onDelete(obj interface{}) {
 		log.Errorf("found ApisixGlobalRule resource with bad meta namesagre key: %s", err)
 		return
 	}
+	if !c.isEffective(agr) {
+		return
+	}
 	if !c.namespaceProvider.IsWatchingNamespace(key) {
 		return
 	}
@@ -332,10 +340,13 @@ func (c *apisixGlobalRuleController) ResourceSync() {
 			log.Errorw("ApisixGlobalRule sync failed, found ApisixGlobalRule resource with bad meta namespace key", zap.String("error", err.Error()))
 			continue
 		}
+		agr := kube.MustNewApisixGlobalRule(obj)
+		if !c.isEffective(agr) {
+			continue
+		}
 		if !c.namespaceProvider.IsWatchingNamespace(key) {
 			continue
 		}
-		agr := kube.MustNewApisixGlobalRule(obj)
 		c.workqueue.Add(&types.Event{
 			Type: types.EventAdd,
 			Object: kube.ApisixGlobalRuleEvent{
@@ -389,3 +400,20 @@ func (c *apisixGlobalRuleController) recordStatus(at interface{}, reason string,
 		log.Errorf("unsupported resource record: %s", v)
 	}
 }
+
+func (c *apisixGlobalRuleController) isEffective(agr kube.ApisixGlobalRule) bool {
+	if agr.GroupVersion() == config.ApisixV2 {
+		ingClassName := agr.V2().Spec.IngressClassName
+		ok := utils.MatchCRDsIngressClass(ingClassName, c.Kubernetes.IngressClass)
+		if !ok {
+			log.Debugw("IngressClass: ApisixGlobalRule ignored",
+				zap.String("key", agr.V2().Namespace+"/"+agr.V2().Name),
+				zap.String("ingressClass", agr.V2().Spec.IngressClassName),
+			)
+		}
+
+		return ok
+	}
+	// Compatible with legacy versions
+	return true
+}
diff --git a/samples/deploy/crd/v1/ApisixGlobalRule.yaml b/samples/deploy/crd/v1/ApisixGlobalRule.yaml
index 0c461db9..7eff6f87 100644
--- a/samples/deploy/crd/v1/ApisixGlobalRule.yaml
+++ b/samples/deploy/crd/v1/ApisixGlobalRule.yaml
@@ -48,6 +48,8 @@ spec:
               required:
                 - plugins
               properties:
+                ingressClassName:
+                  type: string
                 plugins:
                   type: array
                   items:
diff --git a/test/e2e/suite-ingress/suite-ingress-features/ingress-class.go b/test/e2e/suite-ingress/suite-ingress-features/ingress-class.go
index dc5c0672..b0292f48 100644
--- a/test/e2e/suite-ingress/suite-ingress-features/ingress-class.go
+++ b/test/e2e/suite-ingress/suite-ingress-features/ingress-class.go
@@ -472,6 +472,88 @@ spec:
 		assert.Contains(ginkgo.GinkgoT(), acs[0].Username, "james")
 		assert.Equal(ginkgo.GinkgoT(), map[string]interface{}{"key": "james-key"}, acs[0].Plugins["key-auth"])
 	})
+
+	ginkgo.It("ApisixGlobalRule should be ignored", func() {
+		agr := `
+apiVersion: apisix.apache.org/v2
+kind: ApisixGlobalRule
+metadata:
+  name: test-agr-1
+spec:
+  ingressClassName: ignore
+  plugins:
+  - name: echo
+    enable: true
+    config:
+      body: "hello, world!!"
+`
+		assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(agr), "creating ApisixGlobalRule")
+		time.Sleep(6 * time.Second)
+
+		grs, err := s.ListApisixGlobalRules()
+		assert.Nil(ginkgo.GinkgoT(), err, "listing global_rules")
+		assert.Len(ginkgo.GinkgoT(), grs, 0)
+
+		s.NewAPISIXClient().GET("/anything").Expect().Body().NotContains("hello, world!!")
+		s.NewAPISIXClient().GET("/hello").Expect().Body().NotContains("hello, world!!")
+	})
+
+	ginkgo.It("ApisixGlobalRule should be handled", func() {
+		agr := `
+apiVersion: apisix.apache.org/v2
+kind: ApisixGlobalRule
+metadata:
+  name: test-agr-1
+spec:
+  ingressClassName: apisix
+  plugins:
+  - name: echo
+    enable: true
+    config:
+      body: "hello, world!!"
+`
+		assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(agr), "creating ApisixGlobalRule")
+		time.Sleep(6 * time.Second)
+
+		grs, err := s.ListApisixGlobalRules()
+		assert.Nil(ginkgo.GinkgoT(), err, "listing global_rules")
+		assert.Len(ginkgo.GinkgoT(), grs, 1)
+		assert.Len(ginkgo.GinkgoT(), grs[0].Plugins, 1)
+		_, ok := grs[0].Plugins["echo"]
+		assert.Equal(ginkgo.GinkgoT(), ok, true)
+
+		s.NewAPISIXClient().GET("/anything").Expect().Body().Contains("hello, world!!")
+
+		s.NewAPISIXClient().GET("/hello").Expect().Body().Contains("hello, world!!")
+	})
+
+	ginkgo.It("ApisixGlobalRule should be without ingressClass", func() {
+		agr := `
+apiVersion: apisix.apache.org/v2
+kind: ApisixGlobalRule
+metadata:
+  name: test-agr-1
+spec:
+  plugins:
+  - name: echo
+    enable: true
+    config:
+      body: "hello, world!!"
+`
+		assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(agr), "creating ApisixGlobalRule")
+		time.Sleep(6 * time.Second)
+
+		grs, err := s.ListApisixGlobalRules()
+		assert.Nil(ginkgo.GinkgoT(), err, "listing global_rules")
+		assert.Len(ginkgo.GinkgoT(), grs, 1)
+		assert.Len(ginkgo.GinkgoT(), grs[0].Plugins, 1)
+		_, ok := grs[0].Plugins["echo"]
+		assert.Equal(ginkgo.GinkgoT(), ok, true)
+
+		s.NewAPISIXClient().GET("/anything").Expect().Body().Contains("hello, world!!")
+
+		s.NewAPISIXClient().GET("/hello").Expect().Body().Contains("hello, world!!")
+	})
 })
 
 var _ = ginkgo.Describe("suite-ingress-features: Testing CRDs with IngressClass apisix-and-all", func() {
@@ -770,4 +852,61 @@ spec:
 		assert.Contains(ginkgo.GinkgoT(), acs[0].Username, "james")
 		assert.Equal(ginkgo.GinkgoT(), map[string]interface{}{"key": "james-password"}, acs[0].Plugins["key-auth"])
 	})
+
+	ginkgo.It("ApisixGlobalRule should be handled", func() {
+		agr := `
+apiVersion: apisix.apache.org/v2
+kind: ApisixGlobalRule
+metadata:
+  name: test-agr-1
+spec:
+  ingressClassName: apisix
+  plugins:
+  - name: echo
+    enable: true
+    config:
+      body: "hello, world!!"
+`
+		assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(agr), "creating ApisixGlobalRule")
+		time.Sleep(6 * time.Second)
+
+		grs, err := s.ListApisixGlobalRules()
+		assert.Nil(ginkgo.GinkgoT(), err, "listing global_rules")
+		assert.Len(ginkgo.GinkgoT(), grs, 1)
+		assert.Len(ginkgo.GinkgoT(), grs[0].Plugins, 1)
+		_, ok := grs[0].Plugins["echo"]
+		assert.Equal(ginkgo.GinkgoT(), ok, true)
+
+		s.NewAPISIXClient().GET("/anything").Expect().Body().Contains("hello, world!!")
+
+		s.NewAPISIXClient().GET("/hello").Expect().Body().Contains("hello, world!!")
+	})
+
+	ginkgo.It("ApisixGlobalRule should be without ingressClass", func() {
+		agr := `
+apiVersion: apisix.apache.org/v2
+kind: ApisixGlobalRule
+metadata:
+  name: test-agr-1
+spec:
+  plugins:
+  - name: echo
+    enable: true
+    config:
+      body: "hello, world!!"
+`
+		assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(agr), "creating ApisixGlobalRule")
+		time.Sleep(6 * time.Second)
+
+		grs, err := s.ListApisixGlobalRules()
+		assert.Nil(ginkgo.GinkgoT(), err, "listing global_rules")
+		assert.Len(ginkgo.GinkgoT(), grs, 1)
+		assert.Len(ginkgo.GinkgoT(), grs[0].Plugins, 1)
+		_, ok := grs[0].Plugins["echo"]
+		assert.Equal(ginkgo.GinkgoT(), ok, true)
+
+		s.NewAPISIXClient().GET("/anything").Expect().Body().Contains("hello, world!!")
+
+		s.NewAPISIXClient().GET("/hello").Expect().Body().Contains("hello, world!!")
+	})
 })