diff --git a/go.mod b/go.mod index 522a81f835..1c0833a81a 100644 --- a/go.mod +++ b/go.mod @@ -79,13 +79,13 @@ require ( go.uber.org/atomic v1.10.0 // indirect golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect golang.org/x/crypto v0.5.0 // indirect - golang.org/x/mod v0.7.0 // indirect + golang.org/x/mod v0.8.0 // indirect golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect golang.org/x/sys v0.5.0 // indirect golang.org/x/term v0.5.0 // indirect golang.org/x/text v0.7.0 // indirect golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect - golang.org/x/tools v0.4.0 // indirect + golang.org/x/tools v0.6.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/go.sum b/go.sum index 48b0f181d5..0e7844c17b 100644 --- a/go.sum +++ b/go.sum @@ -395,8 +395,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= -golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -557,8 +557,8 @@ golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.4.0 h1:7mTAgkunk3fr4GAloyyCasadO6h9zSsQZbwvcaIciV4= -golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/pkg/kube/apisix/apis/config/v2/types.go b/pkg/kube/apisix/apis/config/v2/types.go index b016d6c3f9..59569caead 100644 --- a/pkg/kube/apisix/apis/config/v2/types.go +++ b/pkg/kube/apisix/apis/config/v2/types.go @@ -43,8 +43,9 @@ type ApisixStatus struct { // ApisixRouteSpec is the spec definition for ApisixRouteSpec. type ApisixRouteSpec struct { - HTTP []ApisixRouteHTTP `json:"http,omitempty" yaml:"http,omitempty"` - Stream []ApisixRouteStream `json:"stream,omitempty" yaml:"stream,omitempty"` + IngressClassName string `json:"ingressClassName,omitempty" yaml:"ingressClassName,omitempty"` + HTTP []ApisixRouteHTTP `json:"http,omitempty" yaml:"http,omitempty"` + Stream []ApisixRouteStream `json:"stream,omitempty" yaml:"stream,omitempty"` } // UpstreamTimeout is settings for the read, send and connect to the upstream. diff --git a/pkg/providers/apisix/apisix_route.go b/pkg/providers/apisix/apisix_route.go index d051fb5a45..18b66e24eb 100644 --- a/pkg/providers/apisix/apisix_route.go +++ b/pkg/providers/apisix/apisix_route.go @@ -534,6 +534,14 @@ func (c *apisixRouteController) handleSyncErr(obj interface{}, errOrigin error) c.MetricsCollector.IncrSyncOperation("route", "failure") } +func (c *apisixRouteController) isEffective(ar kube.ApisixRoute) bool { + if ar.GroupVersion() == config.ApisixV2 { + return utils.MatchCRDsIngressClass(ar.V2().Spec.IngressClassName, c.Kubernetes.IngressClass) + } + // Compatible with legacy versions + return true +} + func (c *apisixRouteController) onAdd(obj interface{}) { key, err := cache.MetaNamespaceKeyFunc(obj) if err != nil { @@ -549,6 +557,12 @@ func (c *apisixRouteController) onAdd(obj interface{}) { ) ar := kube.MustNewApisixRoute(obj) + if !c.isEffective(ar) { + log.Debugw("ignore noneffective ApisixRoute add event", + zap.Any("object", obj), + ) + return + } c.workqueue.Add(&types.Event{ Type: types.EventAdd, Object: kube.ApisixRouteEvent{ @@ -579,6 +593,13 @@ func (c *apisixRouteController) onUpdate(oldObj, newObj interface{}) { zap.Any("new object", oldObj), zap.Any("old object", newObj), ) + if !c.isEffective(curr) { + log.Debugw("ignore noneffective ApisixRoute update event arrived", + zap.Any("new object", curr), + zap.Any("old object", prev), + ) + return + } c.workqueue.Add(&types.Event{ Type: types.EventUpdate, Object: kube.ApisixRouteEvent{ @@ -612,6 +633,12 @@ func (c *apisixRouteController) onDelete(obj interface{}) { zap.String("key", key), zap.Any("final state", ar), ) + if !c.isEffective(ar) { + log.Debugw("ignore noneffective ApisixRoute delete event arrived", + zap.Any("final state", ar), + ) + return + } c.workqueue.Add(&types.Event{ Type: types.EventDelete, Object: kube.ApisixRouteEvent{ @@ -647,6 +674,12 @@ func (c *apisixRouteController) ResourceSync() { continue } ar := kube.MustNewApisixRoute(obj) + if !c.isEffective(ar) { + log.Debugw("ignore noneffective ApisixRoute sync event arrived", + zap.Any("final state", ar), + ) + continue + } c.workqueue.Add(&types.Event{ Type: types.EventAdd, Object: kube.ApisixRouteEvent{ diff --git a/samples/deploy/crd/v1/ApisixRoute.yaml b/samples/deploy/crd/v1/ApisixRoute.yaml index e0f4a0768d..8479d6ccea 100644 --- a/samples/deploy/crd/v1/ApisixRoute.yaml +++ b/samples/deploy/crd/v1/ApisixRoute.yaml @@ -344,6 +344,8 @@ spec: - required: ["http"] - required: ["stream"] properties: + ingressClassName: + type: string http: type: array minItems: 1 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 b0292f48ec..033f9e4081 100644 --- a/test/e2e/suite-ingress/suite-ingress-features/ingress-class.go +++ b/test/e2e/suite-ingress/suite-ingress-features/ingress-class.go @@ -336,7 +336,7 @@ spec: resp.Body().IsEqual("my custom body") }) - ginkgo.It("ApisiTls should be handled", func() { + ginkgo.It("ApisixTls should be handled", func() { err := s.NewSecret(_secretName, _cert, _key) assert.Nil(ginkgo.GinkgoT(), err, "create secret error") // create ApisixTls resource without ingressClassName @@ -365,7 +365,7 @@ spec: assert.Equal(ginkgo.GinkgoT(), tls[0].Snis[0], host2, "tls host is error") }) - ginkgo.It("ApisiTls should be ignored", func() { + ginkgo.It("ApisixTls should be ignored", func() { err := s.NewSecret(_secretName, _cert, _key) assert.Nil(ginkgo.GinkgoT(), err, "create secret error") // create ApisixTls resource with ingressClassName: ignored @@ -554,6 +554,100 @@ spec: s.NewAPISIXClient().GET("/hello").Expect().Body().Contains("hello, world!!") }) + + ginkgo.It("ApisixRoute should be ignored", func() { + backendSvc, backendSvcPort := s.DefaultHTTPBackend() + + ar := fmt.Sprintf(` +apiVersion: apisix.apache.org/v2 +kind: ApisixRoute +metadata: + name: test-ar-1 +spec: + ingressClassName: ignore + http: + - name: rule1 + match: + hosts: + - httpbin.org + paths: + - /ip + backends: + - serviceName: %s + servicePort: %d +`, backendSvc, backendSvcPort[0]) + + assert.Nil(ginkgo.GinkgoT(), s.CreateVersionedApisixResource(ar)) + + // The referenced plugin doesn't exist so the translation expected to be failed + err := s.EnsureNumApisixUpstreamsCreated(0) + assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams") + err = s.EnsureNumApisixRoutesCreated(0) + assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes") + }) + + ginkgo.It("ApisixRoute should be handled", func() { + backendSvc, backendPorts := s.DefaultHTTPBackend() + + ar := fmt.Sprintf(` +apiVersion: apisix.apache.org/v2 +kind: ApisixRoute +metadata: + name: test-ar-1 +spec: + ingressClassName: apisix + http: + - name: rule1 + match: + hosts: + - httpbin.org + paths: + - /ip + backends: + - serviceName: %s + servicePort: %d +`, backendSvc, backendPorts[0]) + + assert.Nil(ginkgo.GinkgoT(), s.CreateVersionedApisixResource(ar)) + + err := s.EnsureNumApisixUpstreamsCreated(1) + assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams") + err = s.EnsureNumApisixRoutesCreated(1) + assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes") + + s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.org").Expect().Status(http.StatusOK) + }) + + ginkgo.It("ApisixRoute should be handled without ingressClass", func() { + backendSvc, backendPorts := s.DefaultHTTPBackend() + ar := fmt.Sprintf(` +apiVersion: apisix.apache.org/v2 +kind: ApisixRoute +metadata: + name: test-ar-1 +spec: + http: + - name: rule1 + match: + hosts: + - httpbin.org + paths: + - /ip + backends: + - serviceName: %s + servicePort: %d + weight: 10 +`, backendSvc, backendPorts[0]) + + assert.Nil(ginkgo.GinkgoT(), s.CreateVersionedApisixResource(ar)) + + err := s.EnsureNumApisixUpstreamsCreated(1) + assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams") + err = s.EnsureNumApisixRoutesCreated(1) + assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes") + + s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.org").Expect().Status(http.StatusOK) + }) }) var _ = ginkgo.Describe("suite-ingress-features: Testing CRDs with IngressClass apisix-and-all", func() { @@ -741,7 +835,7 @@ spec: resp.Body().IsEqual("my custom body") }) - ginkgo.It("ApisiTls should be handled", func() { + ginkgo.It("ApisixTls should be handled", func() { err := s.NewSecret(_secretName, _cert, _key) assert.Nil(ginkgo.GinkgoT(), err, "create secret error") // create ApisixTls resource without ingressClassName @@ -909,4 +1003,68 @@ spec: s.NewAPISIXClient().GET("/hello").Expect().Body().Contains("hello, world!!") }) + + ginkgo.It("ApisixRoute should be handled", func() { + backendSvc, backendPorts := s.DefaultHTTPBackend() + + ar := fmt.Sprintf(` +apiVersion: apisix.apache.org/v2 +kind: ApisixRoute +metadata: + name: test-ar-1 +spec: + ingressClassName: apisix + http: + - name: rule1 + match: + hosts: + - httpbin.org + paths: + - /ip + backends: + - serviceName: %s + servicePort: %d +`, backendSvc, backendPorts[0]) + + assert.Nil(ginkgo.GinkgoT(), s.CreateVersionedApisixResource(ar)) + + err := s.EnsureNumApisixUpstreamsCreated(1) + assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams") + err = s.EnsureNumApisixRoutesCreated(1) + assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes") + + s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.org").Expect().Status(http.StatusOK) + }) + + ginkgo.It("ApisixRoute should be handled without ingressClass", func() { + backendSvc, backendPorts := s.DefaultHTTPBackend() + + ar := fmt.Sprintf(` +apiVersion: apisix.apache.org/v2 +kind: ApisixRoute +metadata: + name: test-ar-1 +spec: + http: + - name: rule1 + match: + hosts: + - httpbin.org + paths: + - /ip + backends: + - serviceName: %s + servicePort: %d + weight: 10 +`, backendSvc, backendPorts[0]) + + assert.Nil(ginkgo.GinkgoT(), s.CreateVersionedApisixResource(ar)) + + err := s.EnsureNumApisixUpstreamsCreated(1) + assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams") + err = s.EnsureNumApisixRoutesCreated(1) + assert.Nil(ginkgo.GinkgoT(), err, "Checking number of routes") + + s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.org").Expect().Status(http.StatusOK) + }) })