You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by zh...@apache.org on 2022/03/02 11:51:26 UTC
[apisix-ingress-controller] branch master updated: fix: check if stream_routes is disabled (#868)
This is an automated email from the ASF dual-hosted git repository.
zhangjintao 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 035c60e fix: check if stream_routes is disabled (#868)
035c60e is described below
commit 035c60e456abf064af23634822f8453606fc5cc5
Author: Sarasa Kisaragi <li...@gmail.com>
AuthorDate: Wed Mar 2 19:51:19 2022 +0800
fix: check if stream_routes is disabled (#868)
---
pkg/apisix/cluster.go | 35 +++++++++++++++---
pkg/apisix/noop.go | 51 +++++++++++++++++++++++++++
pkg/apisix/stream_route.go | 8 ++++-
test/e2e/ingress/sanity.go | 46 ++++++++++++++++++++++++
test/e2e/testdata/apisix-stream-disabled.yaml | 42 ++++++++++++++++++++++
5 files changed, 176 insertions(+), 6 deletions(-)
diff --git a/pkg/apisix/cluster.go b/pkg/apisix/cluster.go
index 8b7a938..20565bb 100644
--- a/pkg/apisix/cluster.go
+++ b/pkg/apisix/cluster.go
@@ -53,6 +53,8 @@ var (
// ErrDuplicatedCluster means the cluster adding request was
// rejected since the cluster was already created.
ErrDuplicatedCluster = errors.New("duplicated cluster")
+ // ErrFunctionDisabled means the APISIX function is disabled
+ ErrFunctionDisabled = errors.New("function disabled")
_errReadOnClosedResBody = errors.New("http: read on closed response body")
@@ -517,6 +519,10 @@ func (c *cluster) do(req *http.Request) (*http.Response, error) {
return c.cli.Do(req)
}
+func (c *cluster) isFunctionDisabled(body string) bool {
+ return strings.Contains(body, "is disabled")
+}
+
func (c *cluster) getResource(ctx context.Context, url, resource string) (*getResponse, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
@@ -532,11 +538,15 @@ func (c *cluster) getResource(ctx context.Context, url, resource string) (*getRe
defer drainBody(resp.Body, url)
if resp.StatusCode != http.StatusOK {
+ body := readBody(resp.Body, url)
+ if c.isFunctionDisabled(body) {
+ return nil, ErrFunctionDisabled
+ }
if resp.StatusCode == http.StatusNotFound {
return nil, cache.ErrNotFound
} else {
err = multierr.Append(err, fmt.Errorf("unexpected status code %d", resp.StatusCode))
- err = multierr.Append(err, fmt.Errorf("error message: %s", readBody(resp.Body, url)))
+ err = multierr.Append(err, fmt.Errorf("error message: %s", body))
}
return nil, err
}
@@ -565,8 +575,12 @@ func (c *cluster) listResource(ctx context.Context, url, resource string) (*list
defer drainBody(resp.Body, url)
if resp.StatusCode != http.StatusOK {
+ body := readBody(resp.Body, url)
+ if c.isFunctionDisabled(body) {
+ return nil, ErrFunctionDisabled
+ }
err = multierr.Append(err, fmt.Errorf("unexpected status code %d", resp.StatusCode))
- err = multierr.Append(err, fmt.Errorf("error message: %s", readBody(resp.Body, url)))
+ err = multierr.Append(err, fmt.Errorf("error message: %s", body))
return nil, err
}
@@ -595,8 +609,12 @@ func (c *cluster) createResource(ctx context.Context, url, resource string, body
defer drainBody(resp.Body, url)
if resp.StatusCode != http.StatusCreated && resp.StatusCode != http.StatusOK {
+ body := readBody(resp.Body, url)
+ if c.isFunctionDisabled(body) {
+ return nil, ErrFunctionDisabled
+ }
err = multierr.Append(err, fmt.Errorf("unexpected status code %d", resp.StatusCode))
- err = multierr.Append(err, fmt.Errorf("error message: %s", readBody(resp.Body, url)))
+ err = multierr.Append(err, fmt.Errorf("error message: %s", body))
return nil, err
}
@@ -624,8 +642,12 @@ func (c *cluster) updateResource(ctx context.Context, url, resource string, body
defer drainBody(resp.Body, url)
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated {
+ body := readBody(resp.Body, url)
+ if c.isFunctionDisabled(body) {
+ return nil, ErrFunctionDisabled
+ }
err = multierr.Append(err, fmt.Errorf("unexpected status code %d", resp.StatusCode))
- err = multierr.Append(err, fmt.Errorf("error message: %s", readBody(resp.Body, url)))
+ err = multierr.Append(err, fmt.Errorf("error message: %s", body))
return nil, err
}
var ur updateResponse
@@ -652,8 +674,11 @@ func (c *cluster) deleteResource(ctx context.Context, url, resource string) erro
defer drainBody(resp.Body, url)
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNoContent && resp.StatusCode != http.StatusNotFound {
- err = multierr.Append(err, fmt.Errorf("unexpected status code %d", resp.StatusCode))
message := readBody(resp.Body, url)
+ if c.isFunctionDisabled(message) {
+ return ErrFunctionDisabled
+ }
+ err = multierr.Append(err, fmt.Errorf("unexpected status code %d", resp.StatusCode))
err = multierr.Append(err, fmt.Errorf("error message: %s", message))
if strings.Contains(message, "still using") {
return cache.ErrStillInUse
diff --git a/pkg/apisix/noop.go b/pkg/apisix/noop.go
new file mode 100644
index 0000000..af7dd87
--- /dev/null
+++ b/pkg/apisix/noop.go
@@ -0,0 +1,51 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+//
+package apisix
+
+import (
+ "context"
+
+ v1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
+)
+
+var (
+ _ StreamRoute = (*noopClient)(nil)
+)
+
+type noopClient struct {
+}
+
+func (r *noopClient) Get(ctx context.Context, name string) (*v1.StreamRoute, error) {
+ return nil, nil
+}
+
+func (r *noopClient) List(ctx context.Context) ([]*v1.StreamRoute, error) {
+ return nil, nil
+}
+
+func (r *noopClient) Create(ctx context.Context, obj *v1.StreamRoute) (*v1.StreamRoute, error) {
+ return nil, nil
+}
+
+func (r *noopClient) Delete(ctx context.Context, obj *v1.StreamRoute) error {
+ return nil
+}
+
+func (r *noopClient) Update(ctx context.Context, obj *v1.StreamRoute) (*v1.StreamRoute, error) {
+ return nil, nil
+}
diff --git a/pkg/apisix/stream_route.go b/pkg/apisix/stream_route.go
index e835eab..f6377c8 100644
--- a/pkg/apisix/stream_route.go
+++ b/pkg/apisix/stream_route.go
@@ -33,8 +33,14 @@ type streamRouteClient struct {
}
func newStreamRouteClient(c *cluster) StreamRoute {
+ url := c.baseURL + "/stream_routes"
+ _, err := c.listResource(context.Background(), url, "streamRoute")
+ if err == ErrFunctionDisabled {
+ log.Infow("resource stream_routes is disabled")
+ return &noopClient{}
+ }
return &streamRouteClient{
- url: c.baseURL + "/stream_routes",
+ url: url,
cluster: c,
}
}
diff --git a/test/e2e/ingress/sanity.go b/test/e2e/ingress/sanity.go
index ff3dd45..08247f7 100644
--- a/test/e2e/ingress/sanity.go
+++ b/test/e2e/ingress/sanity.go
@@ -186,3 +186,49 @@ var _ = ginkgo.Describe("leader election", func() {
}
})
})
+
+var _ = ginkgo.Describe("stream_routes disabled", func() {
+ opts := &scaffold.Options{
+ Name: "default",
+ Kubeconfig: scaffold.GetKubeconfig(),
+ APISIXConfigPath: "testdata/apisix-stream-disabled.yaml",
+ IngressAPISIXReplicas: 1,
+ HTTPBinServicePort: 80,
+ APISIXRouteVersion: "apisix.apache.org/v2beta3",
+ }
+ s := scaffold.NewScaffold(opts)
+ ginkgo.It("/ip should return your ip", func() {
+ backendSvc, backendSvcPort := s.DefaultHTTPBackend()
+ ar := fmt.Sprintf(`
+apiVersion: apisix.apache.org/v2beta3
+kind: ApisixRoute
+metadata:
+ name: httpbin-route
+spec:
+ http:
+ - name: rule1
+ match:
+ paths:
+ - /ip
+ backends:
+ - serviceName: %s
+ servicePort: %d
+`, backendSvc, backendSvcPort[0])
+ assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ar))
+ err := s.EnsureNumApisixRoutesCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "checking number of routes")
+ err = s.EnsureNumApisixUpstreamsCreated(1)
+ assert.Nil(ginkgo.GinkgoT(), err, "checking number of upstreams")
+
+ // TODO When ingress controller can feedback the lifecycle of CRDs to the
+ // status field, we can poll it rather than sleeping.
+ time.Sleep(3 * time.Second)
+
+ body := s.NewAPISIXClient().GET("/ip").WithHeader("Host", "httpbin.com").Expect().Status(http.StatusOK).Body().Raw()
+ var placeholder ip
+ err = json.Unmarshal([]byte(body), &placeholder)
+ assert.Nil(ginkgo.GinkgoT(), err, "unmarshalling IP")
+ // It's not our focus point to check the IP address returned by httpbin,
+ // so here skip the IP address validation.
+ })
+})
diff --git a/test/e2e/testdata/apisix-stream-disabled.yaml b/test/e2e/testdata/apisix-stream-disabled.yaml
new file mode 100644
index 0000000..458b707
--- /dev/null
+++ b/test/e2e/testdata/apisix-stream-disabled.yaml
@@ -0,0 +1,42 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# PLEASE DO NOT UPDATE THIS FILE!
+# If you want to set the specified configuration value, you can set the new
+# value in the conf/config.yaml file.
+#
+
+apisix:
+ enable_control: true
+ enable_reuseport: true # Enable nginx SO_REUSEPORT switch if set to true.
+ allow_admin:
+ - 127.0.0.0/24
+ - 0.0.0.0/0
+ port_admin: 9180
+# stream_proxy: # TCP/UDP proxy
+# only: false
+# tcp: # TCP proxy port list
+# - 9100
+# udp:
+# - 9200
+etcd:
+ host: # it's possible to define multiple etcd hosts addresses of the same etcd cluster.
+ - "http://{{ .EtcdServiceFQDN }}:2379" # multiple etcd address
+ prefix: "/apisix" # apisix configurations prefix
+ timeout: 30 # 30 seconds
+plugin_attr:
+ prometheus:
+ enable_export_server: false