This is an automated email from the ASF dual-hosted git repository.
tokers 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 0460a09 feat: add ApisixClusterConfig CRD and global_rule type,
client (#411)
0460a09 is described below
commit 0460a092004d5029c3936be91fbfe667291f73ed
Author: Alex Zhang <[email protected]>
AuthorDate: Thu May 6 10:29:04 2021 +0800
feat: add ApisixClusterConfig CRD and global_rule type, client (#411)
---
pkg/apisix/apisix.go | 10 +
pkg/apisix/cache/cache.go | 8 +
pkg/apisix/cache/memdb.go | 28 +++
pkg/apisix/cache/memdb_test.go | 43 ++++
pkg/apisix/cache/schema.go | 10 +
pkg/apisix/cluster.go | 32 +++
pkg/apisix/global_rule.go | 223 +++++++++++++++++++++
pkg/apisix/global_rule_test.go | 199 ++++++++++++++++++
pkg/apisix/nonexistentclient.go | 28 +++
pkg/apisix/resource.go | 10 +
pkg/kube/apisix/apis/config/v2alpha1/types.go | 72 +++++++
.../apis/config/v2alpha1/zz_generated.deepcopy.go | 152 ++++++++++++++
.../typed/config/v2alpha1/apisixclusterconfig.go | 168 ++++++++++++++++
.../typed/config/v2alpha1/config_client.go | 5 +
.../v2alpha1/fake/fake_apisixclusterconfig.go | 122 +++++++++++
.../config/v2alpha1/fake/fake_config_client.go | 4 +
.../typed/config/v2alpha1/generated_expansion.go | 2 +
.../config/v2alpha1/apisixclusterconfig.go | 89 ++++++++
.../externalversions/config/v2alpha1/interface.go | 7 +
.../client/informers/externalversions/generic.go | 2 +
.../listers/config/v2alpha1/apisixclusterconfig.go | 68 +++++++
.../listers/config/v2alpha1/expansion_generated.go | 4 +
pkg/types/apisix/v1/types.go | 9 +-
pkg/types/apisix/v1/zz_generated.deepcopy.go | 17 ++
.../deploy/crd/v1beta1/ApisixClusterConfig.yaml | 71 +++++++
samples/deploy/crd/v1beta1/kustomization.yaml | 1 +
26 files changed, 1383 insertions(+), 1 deletion(-)
diff --git a/pkg/apisix/apisix.go b/pkg/apisix/apisix.go
index 0e88f43..e407b7e 100644
--- a/pkg/apisix/apisix.go
+++ b/pkg/apisix/apisix.go
@@ -87,6 +87,16 @@ type StreamRoute interface {
Update(context.Context, *v1.StreamRoute) (*v1.StreamRoute, error)
}
+// GlobalRule is the specific client interface to take over the create, update,
+// list and delete for APISIX's Global Rule resource.
+type GlobalRule interface {
+ Get(context.Context, string) (*v1.GlobalRule, error)
+ List(context.Context) ([]*v1.GlobalRule, error)
+ Create(context.Context, *v1.GlobalRule) (*v1.GlobalRule, error)
+ Delete(context.Context, *v1.GlobalRule) error
+ Update(context.Context, *v1.GlobalRule) (*v1.GlobalRule, error)
+}
+
type apisix struct {
nonExistentCluster Cluster
clusters map[string]Cluster
diff --git a/pkg/apisix/cache/cache.go b/pkg/apisix/cache/cache.go
index c527157..c213f3e 100644
--- a/pkg/apisix/cache/cache.go
+++ b/pkg/apisix/cache/cache.go
@@ -31,6 +31,8 @@ type Cache interface {
InsertUpstream(*v1.Upstream) error
// InsertStreamRoute adds or updates stream_route to cache.
InsertStreamRoute(*v1.StreamRoute) error
+ // InsertGlobalRule adds or updates global_rule to cache.
+ InsertGlobalRule(*v1.GlobalRule) error
// GetRoute finds the route from cache according to the primary index
(id).
GetRoute(string) (*v1.Route, error)
@@ -40,6 +42,8 @@ type Cache interface {
GetUpstream(string) (*v1.Upstream, error)
// GetStreamRoute finds the stream_route from cache according to the
primary index (id).
GetStreamRoute(string) (*v1.StreamRoute, error)
+ // GetGlobalRule finds the global_rule from cache according to the
primary index (id).
+ GetGlobalRule(string) (*v1.GlobalRule, error)
// ListRoutes lists all routes in cache.
ListRoutes() ([]*v1.Route, error)
@@ -49,6 +53,8 @@ type Cache interface {
ListUpstreams() ([]*v1.Upstream, error)
// ListStreamRoutes lists all stream_route in cache.
ListStreamRoutes() ([]*v1.StreamRoute, error)
+ // ListGlobalRules lists all global_rule objects in cache.
+ ListGlobalRules() ([]*v1.GlobalRule, error)
// DeleteRoute deletes the specified route in cache.
DeleteRoute(*v1.Route) error
@@ -58,4 +64,6 @@ type Cache interface {
DeleteUpstream(*v1.Upstream) error
// DeleteStreamRoute deletes the specified stream_route in cache.
DeleteStreamRoute(*v1.StreamRoute) error
+ // DeleteGlobalRule deletes the specified stream_route in cache.
+ DeleteGlobalRule(*v1.GlobalRule) error
}
diff --git a/pkg/apisix/cache/memdb.go b/pkg/apisix/cache/memdb.go
index 481cfe7..18de938 100644
--- a/pkg/apisix/cache/memdb.go
+++ b/pkg/apisix/cache/memdb.go
@@ -62,6 +62,10 @@ func (c *dbCache) InsertStreamRoute(sr *v1.StreamRoute)
error {
return c.insert("stream_route", sr.DeepCopy())
}
+func (c *dbCache) InsertGlobalRule(gr *v1.GlobalRule) error {
+ return c.insert("global_rule", gr.DeepCopy())
+}
+
func (c *dbCache) insert(table string, obj interface{}) error {
txn := c.db.Txn(true)
defer txn.Abort()
@@ -104,6 +108,14 @@ func (c *dbCache) GetStreamRoute(id string)
(*v1.StreamRoute, error) {
return obj.(*v1.StreamRoute).DeepCopy(), nil
}
+func (c *dbCache) GetGlobalRule(id string) (*v1.GlobalRule, error) {
+ obj, err := c.get("global_rule", id)
+ if err != nil {
+ return nil, err
+ }
+ return obj.(*v1.GlobalRule).DeepCopy(), nil
+}
+
func (c *dbCache) get(table, id string) (interface{}, error) {
txn := c.db.Txn(false)
defer txn.Abort()
@@ -168,6 +180,18 @@ func (c *dbCache) ListStreamRoutes() ([]*v1.StreamRoute,
error) {
return streamRoutes, nil
}
+func (c *dbCache) ListGlobalRules() ([]*v1.GlobalRule, error) {
+ raws, err := c.list("global_rule")
+ if err != nil {
+ return nil, err
+ }
+ globalRules := make([]*v1.GlobalRule, 0, len(raws))
+ for _, raw := range raws {
+ globalRules = append(globalRules,
raw.(*v1.GlobalRule).DeepCopy())
+ }
+ return globalRules, nil
+}
+
func (c *dbCache) list(table string) ([]interface{}, error) {
txn := c.db.Txn(false)
defer txn.Abort()
@@ -201,6 +225,10 @@ func (c *dbCache) DeleteStreamRoute(sr *v1.StreamRoute)
error {
return c.delete("stream_route", sr)
}
+func (c *dbCache) DeleteGlobalRule(gr *v1.GlobalRule) error {
+ return c.delete("global_rule", gr)
+}
+
func (c *dbCache) delete(table string, obj interface{}) error {
txn := c.db.Txn(true)
defer txn.Abort()
diff --git a/pkg/apisix/cache/memdb_test.go b/pkg/apisix/cache/memdb_test.go
index 8e449ea..91858d7 100644
--- a/pkg/apisix/cache/memdb_test.go
+++ b/pkg/apisix/cache/memdb_test.go
@@ -259,3 +259,46 @@ func TestMemDBCacheStreamRoute(t *testing.T) {
}
assert.Error(t, ErrNotFound, c.DeleteStreamRoute(r4))
}
+
+func TestMemDBCacheGlobalRule(t *testing.T) {
+ c, err := NewMemDBCache()
+ assert.Nil(t, err, "NewMemDBCache")
+
+ gr1 := &v1.GlobalRule{
+ ID: "1",
+ }
+ assert.Nil(t, c.InsertGlobalRule(gr1), "inserting global rule 1")
+
+ gr, err := c.GetGlobalRule("1")
+ assert.Nil(t, err)
+ assert.Equal(t, gr1, gr)
+
+ gr2 := &v1.GlobalRule{
+ ID: "2",
+ }
+ gr3 := &v1.GlobalRule{
+ ID: "3",
+ }
+ assert.Nil(t, c.InsertGlobalRule(gr2), "inserting global_rule r2")
+ assert.Nil(t, c.InsertGlobalRule(gr3), "inserting global_rule r3")
+
+ gr, err = c.GetGlobalRule("3")
+ assert.Nil(t, err)
+ assert.Equal(t, gr, gr)
+
+ assert.Nil(t, c.DeleteGlobalRule(gr), "delete global_rule r3")
+
+ grs, err := c.ListGlobalRules()
+ assert.Nil(t, err, "listing global rules")
+
+ if grs[0].ID > grs[1].ID {
+ grs[0], grs[1] = grs[1], grs[0]
+ }
+ assert.Equal(t, grs[0], gr1)
+ assert.Equal(t, grs[1], gr2)
+
+ gr4 := &v1.GlobalRule{
+ ID: "4",
+ }
+ assert.Error(t, ErrNotFound, c.DeleteGlobalRule(gr4))
+}
diff --git a/pkg/apisix/cache/schema.go b/pkg/apisix/cache/schema.go
index 9db4ae7..c3e8877 100644
--- a/pkg/apisix/cache/schema.go
+++ b/pkg/apisix/cache/schema.go
@@ -86,6 +86,16 @@ var (
},
},
},
+ "global_rule": {
+ Name: "global_rule",
+ Indexes: map[string]*memdb.IndexSchema{
+ "id": {
+ Name: "id",
+ Unique: true,
+ Indexer:
&memdb.StringFieldIndex{Field: "ID"},
+ },
+ },
+ },
},
}
)
diff --git a/pkg/apisix/cluster.go b/pkg/apisix/cluster.go
index 362d5d5..bc31ee8 100644
--- a/pkg/apisix/cluster.go
+++ b/pkg/apisix/cluster.go
@@ -73,6 +73,7 @@ type cluster struct {
upstream Upstream
ssl SSL
streamRoute StreamRoute
+ globalRules GlobalRule
}
func newCluster(o *ClusterOptions) (Cluster, error) {
@@ -103,6 +104,7 @@ func newCluster(o *ClusterOptions) (Cluster, error) {
c.upstream = newUpstreamClient(c)
c.ssl = newSSLClient(c)
c.streamRoute = newStreamRouteClient(c)
+ c.globalRules = newGlobalRuleClient(c)
go c.syncCache()
@@ -167,6 +169,16 @@ func (c *cluster) syncCacheOnce() (bool, error) {
log.Errorf("failed to list ssl in APISIX: %s", err)
return false, err
}
+ streamRoutes, err := c.streamRoute.List(context.TODO())
+ if err != nil {
+ log.Errorf("failed to list stream_routes in APISIX: %s", err)
+ return false, err
+ }
+ globalRules, err := c.globalRules.List(context.TODO())
+ if err != nil {
+ log.Errorf("failed to list global_rules in APISIX: %s", err)
+ return false, err
+ }
for _, r := range routes {
if err := c.cache.InsertRoute(r); err != nil {
@@ -198,6 +210,26 @@ func (c *cluster) syncCacheOnce() (bool, error) {
return false, err
}
}
+ for _, sr := range streamRoutes {
+ if err := c.cache.InsertStreamRoute(sr); err != nil {
+ log.Errorw("failed to insert stream_route to cache",
+ zap.Any("stream_route", sr),
+ zap.String("cluster", c.name),
+ zap.String("error", err.Error()),
+ )
+ return false, err
+ }
+ }
+ for _, gr := range globalRules {
+ if err := c.cache.InsertGlobalRule(gr); err != nil {
+ log.Errorw("failed to insert global_rule to cache",
+ zap.Any("global_rule", gr),
+ zap.String("cluster", c.name),
+ zap.String("error", err.Error()),
+ )
+ return false, err
+ }
+ }
return true, nil
}
diff --git a/pkg/apisix/global_rule.go b/pkg/apisix/global_rule.go
new file mode 100644
index 0000000..7060354
--- /dev/null
+++ b/pkg/apisix/global_rule.go
@@ -0,0 +1,223 @@
+// 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 (
+ "bytes"
+ "context"
+ "encoding/json"
+
+ "github.com/apache/apisix-ingress-controller/pkg/apisix/cache"
+ "github.com/apache/apisix-ingress-controller/pkg/id"
+ "github.com/apache/apisix-ingress-controller/pkg/log"
+ v1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
+ "go.uber.org/zap"
+)
+
+type globalRuleClient struct {
+ url string
+ cluster *cluster
+}
+
+func newGlobalRuleClient(c *cluster) GlobalRule {
+ return &globalRuleClient{
+ url: c.baseURL + "/global_rules",
+ cluster: c,
+ }
+}
+
+// Get returns the GlobalRule.
+// FIXME, currently if caller pass a non-existent resource, the Get always
passes
+// through cache.
+func (r *globalRuleClient) Get(ctx context.Context, name string)
(*v1.GlobalRule, error) {
+ log.Debugw("try to look up global_rule",
+ zap.String("name", name),
+ zap.String("url", r.url),
+ zap.String("cluster", "default"),
+ )
+ rid := id.GenID(name)
+ globalRule, err := r.cluster.cache.GetGlobalRule(rid)
+ if err == nil {
+ return globalRule, nil
+ }
+ if err != cache.ErrNotFound {
+ log.Errorw("failed to find global_rule in cache, will try to
lookup from APISIX",
+ zap.String("name", name),
+ zap.Error(err),
+ )
+ } else {
+ log.Debugw("failed to find global_rule in cache, will try to
lookup from APISIX",
+ zap.String("name", name),
+ zap.Error(err),
+ )
+ }
+
+ // TODO Add mutex here to avoid dog-pile effect.
+ url := r.url + "/" + rid
+ resp, err := r.cluster.getResource(ctx, url)
+ if err != nil {
+ if err == cache.ErrNotFound {
+ log.Warnw("global_rule not found",
+ zap.String("name", name),
+ zap.String("url", url),
+ zap.String("cluster", "default"),
+ )
+ } else {
+ log.Errorw("failed to get global_rule from APISIX",
+ zap.String("name", name),
+ zap.String("url", url),
+ zap.String("cluster", "default"),
+ zap.Error(err),
+ )
+ }
+ return nil, err
+ }
+
+ globalRule, err = resp.Item.globalRule()
+ if err != nil {
+ log.Errorw("failed to convert global_rule item",
+ zap.String("url", r.url),
+ zap.String("global_rule_key", resp.Item.Key),
+ zap.String("global_rule_value",
string(resp.Item.Value)),
+ zap.Error(err),
+ )
+ return nil, err
+ }
+
+ if err := r.cluster.cache.InsertGlobalRule(globalRule); err != nil {
+ log.Errorf("failed to reflect global_rule create to cache: %s",
err)
+ return nil, err
+ }
+ return globalRule, nil
+}
+
+// List is only used in cache warming up. So here just pass through
+// to APISIX.
+func (r *globalRuleClient) List(ctx context.Context) ([]*v1.GlobalRule, error)
{
+ log.Debugw("try to list global_rules in APISIX",
+ zap.String("cluster", "default"),
+ zap.String("url", r.url),
+ )
+ globalRuleItems, err := r.cluster.listResource(ctx, r.url)
+ if err != nil {
+ log.Errorf("failed to list global_rules: %s", err)
+ return nil, err
+ }
+
+ var items []*v1.GlobalRule
+ for i, item := range globalRuleItems.Node.Items {
+ globalRule, err := item.globalRule()
+ if err != nil {
+ log.Errorw("failed to convert global_rule item",
+ zap.String("url", r.url),
+ zap.String("global_rule_key", item.Key),
+ zap.String("global_rule_value",
string(item.Value)),
+ zap.Error(err),
+ )
+ return nil, err
+ }
+
+ items = append(items, globalRule)
+ log.Debugf("list global_rule #%d, body: %s", i,
string(item.Value))
+ }
+
+ return items, nil
+}
+
+func (r *globalRuleClient) Create(ctx context.Context, obj *v1.GlobalRule)
(*v1.GlobalRule, error) {
+ log.Debugw("try to create global_rule",
+ zap.String("id", obj.ID),
+ zap.Any("plugins", obj.Plugins),
+ zap.String("cluster", "default"),
+ zap.String("url", r.url),
+ )
+
+ if err := r.cluster.HasSynced(ctx); err != nil {
+ return nil, err
+ }
+ data, err := json.Marshal(obj)
+ if err != nil {
+ return nil, err
+ }
+
+ url := r.url + "/" + obj.ID
+ log.Debugw("creating global_rule", zap.ByteString("body", data),
zap.String("url", url))
+ resp, err := r.cluster.createResource(ctx, url, bytes.NewReader(data))
+ if err != nil {
+ log.Errorf("failed to create global_rule: %s", err)
+ return nil, err
+ }
+
+ globalRules, err := resp.Item.globalRule()
+ if err != nil {
+ return nil, err
+ }
+ if err := r.cluster.cache.InsertGlobalRule(globalRules); err != nil {
+ log.Errorf("failed to reflect global_rules create to cache:
%s", err)
+ return nil, err
+ }
+ return globalRules, nil
+}
+
+func (r *globalRuleClient) Delete(ctx context.Context, obj *v1.GlobalRule)
error {
+ log.Debugw("try to delete global_rule",
+ zap.String("id", obj.ID),
+ zap.String("cluster", "default"),
+ zap.String("url", r.url),
+ )
+ if err := r.cluster.HasSynced(ctx); err != nil {
+ return err
+ }
+ url := r.url + "/" + obj.ID
+ if err := r.cluster.deleteResource(ctx, url); err != nil {
+ return err
+ }
+ if err := r.cluster.cache.DeleteGlobalRule(obj); err != nil {
+ log.Errorf("failed to reflect global_rule delete to cache: %s",
err)
+ return err
+ }
+ return nil
+}
+
+func (r *globalRuleClient) Update(ctx context.Context, obj *v1.GlobalRule)
(*v1.GlobalRule, error) {
+ log.Debugw("try to update global_rule",
+ zap.String("id", obj.ID),
+ zap.Any("plugins", obj.Plugins),
+ zap.String("cluster", "default"),
+ zap.String("url", r.url),
+ )
+ if err := r.cluster.HasSynced(ctx); err != nil {
+ return nil, err
+ }
+ body, err := json.Marshal(obj)
+ if err != nil {
+ return nil, err
+ }
+ url := r.url + "/" + obj.ID
+ log.Debugw("updating global_rule", zap.ByteString("body", body),
zap.String("url", url))
+ resp, err := r.cluster.updateResource(ctx, url, bytes.NewReader(body))
+ if err != nil {
+ return nil, err
+ }
+ globalRule, err := resp.Item.globalRule()
+ if err != nil {
+ return nil, err
+ }
+ if err := r.cluster.cache.InsertGlobalRule(globalRule); err != nil {
+ log.Errorf("failed to reflect global_rule update to cache: %s",
err)
+ return nil, err
+ }
+ return globalRule, nil
+}
diff --git a/pkg/apisix/global_rule_test.go b/pkg/apisix/global_rule_test.go
new file mode 100644
index 0000000..01a4d38
--- /dev/null
+++ b/pkg/apisix/global_rule_test.go
@@ -0,0 +1,199 @@
+// 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"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "sort"
+ "strconv"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "golang.org/x/net/nettest"
+
+ v1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
+)
+
+type fakeAPISIXGlobalRuleSrv struct {
+ globalRule map[string]json.RawMessage
+}
+
+func (srv *fakeAPISIXGlobalRuleSrv) ServeHTTP(w http.ResponseWriter, r
*http.Request) {
+ defer r.Body.Close()
+
+ if !strings.HasPrefix(r.URL.Path, "/apisix/admin/global_rules") {
+ w.WriteHeader(http.StatusNotFound)
+ return
+ }
+
+ if r.Method == http.MethodGet {
+ resp := fakeListResp{
+ Count: strconv.Itoa(len(srv.globalRule)),
+ Node: fakeNode{
+ Key: "/apisix/global_rules",
+ },
+ }
+ var keys []string
+ for key := range srv.globalRule {
+ keys = append(keys, key)
+ }
+ sort.Strings(keys)
+ for _, key := range keys {
+ resp.Node.Items = append(resp.Node.Items, fakeItem{
+ Key: key,
+ Value: srv.globalRule[key],
+ })
+ }
+ w.WriteHeader(http.StatusOK)
+ data, _ := json.Marshal(resp)
+ _, _ = w.Write(data)
+ return
+ }
+
+ if r.Method == http.MethodDelete {
+ id := strings.TrimPrefix(r.URL.Path,
"/apisix/admin/global_rules/")
+ id = "/apisix/admin/global_rules/" + id
+ code := http.StatusNotFound
+ if _, ok := srv.globalRule[id]; ok {
+ delete(srv.globalRule, id)
+ code = http.StatusOK
+ }
+ w.WriteHeader(code)
+ }
+
+ if r.Method == http.MethodPut {
+ paths := strings.Split(r.URL.Path, "/")
+ key := fmt.Sprintf("/apisix/admin/global_rules/%s",
paths[len(paths)-1])
+ data, _ := ioutil.ReadAll(r.Body)
+ srv.globalRule[key] = data
+ w.WriteHeader(http.StatusCreated)
+ resp := fakeCreateResp{
+ Action: "create",
+ Node: fakeItem{
+ Key: key,
+ Value: json.RawMessage(data),
+ },
+ }
+ data, _ = json.Marshal(resp)
+ _, _ = w.Write(data)
+ return
+ }
+
+ if r.Method == http.MethodPatch {
+ id := strings.TrimPrefix(r.URL.Path,
"/apisix/admin/global_rules/")
+ id = "/apisix/global_rules/" + id
+ if _, ok := srv.globalRule[id]; !ok {
+ w.WriteHeader(http.StatusNotFound)
+ return
+ }
+
+ data, _ := ioutil.ReadAll(r.Body)
+ srv.globalRule[id] = data
+
+ w.WriteHeader(http.StatusOK)
+ output := fmt.Sprintf(`{"action": "compareAndSwap", "node":
{"key": "%s", "value": %s}}`, id, string(data))
+ _, _ = w.Write([]byte(output))
+ return
+ }
+}
+
+func runFakeGlobalRuleSrv(t *testing.T) *http.Server {
+ srv := &fakeAPISIXGlobalRuleSrv{
+ globalRule: make(map[string]json.RawMessage),
+ }
+
+ ln, _ := nettest.NewLocalListener("tcp")
+
+ httpSrv := &http.Server{
+ Addr: ln.Addr().String(),
+ Handler: srv,
+ }
+
+ go func() {
+ if err := httpSrv.Serve(ln); err != nil && err !=
http.ErrServerClosed {
+ t.Errorf("failed to run http server: %s", err)
+ }
+ }()
+
+ return httpSrv
+}
+
+func TestGlobalRuleClient(t *testing.T) {
+ srv := runFakeGlobalRuleSrv(t)
+ defer func() {
+ assert.Nil(t, srv.Shutdown(context.Background()))
+ }()
+
+ u := url.URL{
+ Scheme: "http",
+ Host: srv.Addr,
+ Path: "/apisix/admin",
+ }
+
+ closedCh := make(chan struct{})
+ close(closedCh)
+ cli := newGlobalRuleClient(&cluster{
+ baseURL: u.String(),
+ cli: http.DefaultClient,
+ cache: &dummyCache{},
+ cacheSynced: closedCh,
+ })
+
+ // Create
+ obj, err := cli.Create(context.Background(), &v1.GlobalRule{
+ ID: "1",
+ })
+ assert.Nil(t, err)
+ assert.Equal(t, obj.ID, "1")
+
+ obj, err = cli.Create(context.Background(), &v1.GlobalRule{
+ ID: "2",
+ })
+ assert.Nil(t, err)
+ assert.Equal(t, obj.ID, "2")
+
+ // List
+ objs, err := cli.List(context.Background())
+ assert.Nil(t, err)
+ assert.Len(t, objs, 2)
+ assert.Equal(t, objs[0].ID, "1")
+ assert.Equal(t, objs[1].ID, "2")
+
+ // Delete then List
+ assert.Nil(t, cli.Delete(context.Background(), objs[0]))
+ objs, err = cli.List(context.Background())
+ assert.Nil(t, err)
+ assert.Len(t, objs, 1)
+ assert.Equal(t, "2", objs[0].ID)
+
+ // Patch then List
+ _, err = cli.Update(context.Background(), &v1.GlobalRule{
+ ID: "2",
+ Plugins: map[string]interface{}{
+ "prometheus": struct{}{},
+ },
+ })
+ assert.Nil(t, err)
+ objs, err = cli.List(context.Background())
+ assert.Nil(t, err)
+ assert.Len(t, objs, 1)
+ assert.Equal(t, "2", objs[0].ID)
+}
diff --git a/pkg/apisix/nonexistentclient.go b/pkg/apisix/nonexistentclient.go
index 3113bae..d965cda 100644
--- a/pkg/apisix/nonexistentclient.go
+++ b/pkg/apisix/nonexistentclient.go
@@ -33,6 +33,7 @@ func newNonExistentCluster() *nonExistentCluster {
ssl: &dummySSL{},
upstream: &dummyUpstream{},
streamRoute: &dummyStreamRoute{},
+ globalRule: &dummyGlobalRule{},
},
}
}
@@ -42,6 +43,7 @@ type embedDummyResourceImplementer struct {
ssl SSL
upstream Upstream
streamRoute StreamRoute
+ globalRule GlobalRule
}
type dummyRoute struct{}
@@ -132,6 +134,28 @@ func (f *dummyStreamRoute) Update(_ context.Context, _
*v1.StreamRoute) (*v1.Str
return nil, ErrClusterNotExist
}
+type dummyGlobalRule struct{}
+
+func (f *dummyGlobalRule) Get(_ context.Context, _ string) (*v1.GlobalRule,
error) {
+ return nil, ErrClusterNotExist
+}
+
+func (f *dummyGlobalRule) List(_ context.Context) ([]*v1.GlobalRule, error) {
+ return nil, ErrClusterNotExist
+}
+
+func (f *dummyGlobalRule) Create(_ context.Context, _ *v1.GlobalRule)
(*v1.GlobalRule, error) {
+ return nil, ErrClusterNotExist
+}
+
+func (f *dummyGlobalRule) Delete(_ context.Context, _ *v1.GlobalRule) error {
+ return ErrClusterNotExist
+}
+
+func (f *dummyGlobalRule) Update(_ context.Context, _ *v1.GlobalRule)
(*v1.GlobalRule, error) {
+ return nil, ErrClusterNotExist
+}
+
func (nc *nonExistentCluster) Route() Route {
return nc.route
}
@@ -164,15 +188,19 @@ func (c *dummyCache) InsertRoute(_ *v1.Route) error
{ return
func (c *dummyCache) InsertSSL(_ *v1.Ssl) error {
return nil }
func (c *dummyCache) InsertUpstream(_ *v1.Upstream) error {
return nil }
func (c *dummyCache) InsertStreamRoute(_ *v1.StreamRoute) error {
return nil }
+func (c *dummyCache) InsertGlobalRule(_ *v1.GlobalRule) error {
return nil }
func (c *dummyCache) GetRoute(_ string) (*v1.Route, error) {
return nil, cache.ErrNotFound }
func (c *dummyCache) GetSSL(_ string) (*v1.Ssl, error) {
return nil, cache.ErrNotFound }
func (c *dummyCache) GetUpstream(_ string) (*v1.Upstream, error) {
return nil, cache.ErrNotFound }
func (c *dummyCache) GetStreamRoute(_ string) (*v1.StreamRoute, error) {
return nil, cache.ErrNotFound }
+func (c *dummyCache) GetGlobalRule(_ string) (*v1.GlobalRule, error) {
return nil, cache.ErrNotFound }
func (c *dummyCache) ListRoutes() ([]*v1.Route, error) {
return nil, nil }
func (c *dummyCache) ListSSL() ([]*v1.Ssl, error) {
return nil, nil }
func (c *dummyCache) ListUpstreams() ([]*v1.Upstream, error) {
return nil, nil }
func (c *dummyCache) ListStreamRoutes() ([]*v1.StreamRoute, error) {
return nil, nil }
+func (c *dummyCache) ListGlobalRules() ([]*v1.GlobalRule, error) {
return nil, nil }
func (c *dummyCache) DeleteRoute(_ *v1.Route) error {
return nil }
func (c *dummyCache) DeleteSSL(_ *v1.Ssl) error {
return nil }
func (c *dummyCache) DeleteUpstream(_ *v1.Upstream) error {
return nil }
func (c *dummyCache) DeleteStreamRoute(_ *v1.StreamRoute) error {
return nil }
+func (c *dummyCache) DeleteGlobalRule(_ *v1.GlobalRule) error {
return nil }
diff --git a/pkg/apisix/resource.go b/pkg/apisix/resource.go
index 5526a66..d24791f 100644
--- a/pkg/apisix/resource.go
+++ b/pkg/apisix/resource.go
@@ -137,3 +137,13 @@ func (i *item) ssl() (*v1.Ssl, error) {
}
return &ssl, nil
}
+
+// globalRule decodes item.Value and converts it to v1.GlobalRule.
+func (i *item) globalRule() (*v1.GlobalRule, error) {
+ log.Debugf("got global_rule: %s", string(i.Value))
+ var globalRule v1.GlobalRule
+ if err := json.Unmarshal(i.Value, &globalRule); err != nil {
+ return nil, err
+ }
+ return &globalRule, nil
+}
diff --git a/pkg/kube/apisix/apis/config/v2alpha1/types.go
b/pkg/kube/apisix/apis/config/v2alpha1/types.go
index 926addb..2c01b6f 100644
--- a/pkg/kube/apisix/apis/config/v2alpha1/types.go
+++ b/pkg/kube/apisix/apis/config/v2alpha1/types.go
@@ -232,8 +232,80 @@ type ApisixRouteTCPBackend struct {
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ApisixRouteList contains a list of ApisixRoute.
type ApisixRouteList struct {
metav1.TypeMeta `json:",inline" yaml:",inline"`
metav1.ListMeta `json:"metadata" yaml:"metadata"`
Items []ApisixRoute `json:"items,omitempty"
yaml:"items,omitempty"`
}
+
+// +genclient
+// +genclient:nonNamespaced
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// +kubebuilder:subresource:status
+
+// ApisixClusterConfig is the Schema for the ApisixClusterConfig resource.
+// An ApisixClusterConfig is used to identify an APISIX cluster, it's a
+// ClusterScoped resource so the name is unique.
+// It also contains some cluster-level configurations like monitoring.
+type ApisixClusterConfig struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
+
+ // Spec defines the desired state of ApisixClusterConfigSpec.
+ Spec ApisixClusterConfigSpec `json:"spec" yaml:"spec"`
+}
+
+// ApisixClusterConfigSpec defines the desired state of
ApisixClusterConfigSpec.
+type ApisixClusterConfigSpec struct {
+ // Monitoring categories all monitoring related features.
+ // +optional
+ Monitoring *ApisixClusterMonitoringConfig `json:"monitoring"
yaml:"monitoring"`
+ // Admin contains the Admin API information about APISIX cluster.
+ // +optional
+ Admin *ApisixClusterAdminConfig `json:"admin" yaml:"admin"`
+}
+
+// ApisixClusterMonitoringConfig categories all monitoring related features.
+type ApisixClusterMonitoringConfig struct {
+ // Prometheus is the config for using Prometheus in APISIX Cluster.
+ // +optional
+ Prometheus ApisixClusterPrometheusConfig
+ // Skywalking is the config for using Skywalking in APISIX Cluster.
+ // +optional
+ Skywalking ApisixClusterSkywalkingConfig
+}
+
+// ApisixClusterPrometheusConfig is the config for using Prometheus in APISIX
Cluster.
+type ApisixClusterPrometheusConfig struct {
+ // Enable means whether enable Prometheus or not.
+ Enable bool `json:"enable" yaml:"enable"`
+}
+
+// ApisixClusterSkywalkingConfig is the config for using Skywalking in APISIX
Cluster.
+type ApisixClusterSkywalkingConfig struct {
+ // Enable means whether enable Skywalking or not.
+ Enable bool `json:"enable" yaml:"enable"`
+ // SampleRatio means the ratio to collect
+ SampleRatio float64 `json:"sampleRatio" yaml:"sampleRatio"`
+}
+
+// ApisixClusterAdminConfig is the admin config for the corresponding APISIX
Cluster.
+type ApisixClusterAdminConfig struct {
+ // BaseURL is the base URL for the APISIX Admin API.
+ // It looks like
"http://apisix-admin.default.svc.cluster.local:9080/apisix/admin"
+ BaseURL string
+ // AdminKey is used to verify the admin API user.
+ AdminKey string
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// ApisixClusterConfigList contains a list of ApisixClusterConfig.
+type ApisixClusterConfigList struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ListMeta `json:"metadata" yaml:"metadata"`
+
+ Items []ApisixClusterConfig `json:"items" yaml:"items"`
+}
diff --git a/pkg/kube/apisix/apis/config/v2alpha1/zz_generated.deepcopy.go
b/pkg/kube/apisix/apis/config/v2alpha1/zz_generated.deepcopy.go
index 16cedce..c11e22c 100644
--- a/pkg/kube/apisix/apis/config/v2alpha1/zz_generated.deepcopy.go
+++ b/pkg/kube/apisix/apis/config/v2alpha1/zz_generated.deepcopy.go
@@ -26,6 +26,158 @@ import (
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver,
writing into out. in must be non-nil.
+func (in *ApisixClusterAdminConfig) DeepCopyInto(out
*ApisixClusterAdminConfig) {
+ *out = *in
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver,
creating a new ApisixClusterAdminConfig.
+func (in *ApisixClusterAdminConfig) DeepCopy() *ApisixClusterAdminConfig {
+ if in == nil {
+ return nil
+ }
+ out := new(ApisixClusterAdminConfig)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver,
writing into out. in must be non-nil.
+func (in *ApisixClusterConfig) DeepCopyInto(out *ApisixClusterConfig) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+ in.Spec.DeepCopyInto(&out.Spec)
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver,
creating a new ApisixClusterConfig.
+func (in *ApisixClusterConfig) DeepCopy() *ApisixClusterConfig {
+ if in == nil {
+ return nil
+ }
+ out := new(ApisixClusterConfig)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver,
creating a new runtime.Object.
+func (in *ApisixClusterConfig) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver,
writing into out. in must be non-nil.
+func (in *ApisixClusterConfigList) DeepCopyInto(out *ApisixClusterConfigList) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.ListMeta)
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]ApisixClusterConfig, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver,
creating a new ApisixClusterConfigList.
+func (in *ApisixClusterConfigList) DeepCopy() *ApisixClusterConfigList {
+ if in == nil {
+ return nil
+ }
+ out := new(ApisixClusterConfigList)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver,
creating a new runtime.Object.
+func (in *ApisixClusterConfigList) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver,
writing into out. in must be non-nil.
+func (in *ApisixClusterConfigSpec) DeepCopyInto(out *ApisixClusterConfigSpec) {
+ *out = *in
+ if in.Monitoring != nil {
+ in, out := &in.Monitoring, &out.Monitoring
+ *out = new(ApisixClusterMonitoringConfig)
+ **out = **in
+ }
+ if in.Admin != nil {
+ in, out := &in.Admin, &out.Admin
+ *out = new(ApisixClusterAdminConfig)
+ **out = **in
+ }
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver,
creating a new ApisixClusterConfigSpec.
+func (in *ApisixClusterConfigSpec) DeepCopy() *ApisixClusterConfigSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(ApisixClusterConfigSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver,
writing into out. in must be non-nil.
+func (in *ApisixClusterMonitoringConfig) DeepCopyInto(out
*ApisixClusterMonitoringConfig) {
+ *out = *in
+ out.Prometheus = in.Prometheus
+ out.Skywalking = in.Skywalking
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver,
creating a new ApisixClusterMonitoringConfig.
+func (in *ApisixClusterMonitoringConfig) DeepCopy()
*ApisixClusterMonitoringConfig {
+ if in == nil {
+ return nil
+ }
+ out := new(ApisixClusterMonitoringConfig)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver,
writing into out. in must be non-nil.
+func (in *ApisixClusterPrometheusConfig) DeepCopyInto(out
*ApisixClusterPrometheusConfig) {
+ *out = *in
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver,
creating a new ApisixClusterPrometheusConfig.
+func (in *ApisixClusterPrometheusConfig) DeepCopy()
*ApisixClusterPrometheusConfig {
+ if in == nil {
+ return nil
+ }
+ out := new(ApisixClusterPrometheusConfig)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver,
writing into out. in must be non-nil.
+func (in *ApisixClusterSkywalkingConfig) DeepCopyInto(out
*ApisixClusterSkywalkingConfig) {
+ *out = *in
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver,
creating a new ApisixClusterSkywalkingConfig.
+func (in *ApisixClusterSkywalkingConfig) DeepCopy()
*ApisixClusterSkywalkingConfig {
+ if in == nil {
+ return nil
+ }
+ out := new(ApisixClusterSkywalkingConfig)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver,
writing into out. in must be non-nil.
func (in *ApisixRoute) DeepCopyInto(out *ApisixRoute) {
*out = *in
out.TypeMeta = in.TypeMeta
diff --git
a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/apisixclusterconfig.go
b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/apisixclusterconfig.go
new file mode 100644
index 0000000..bcd8c56
--- /dev/null
+++
b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/apisixclusterconfig.go
@@ -0,0 +1,168 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v2alpha1
+
+import (
+ "context"
+ "time"
+
+ v2alpha1
"github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2alpha1"
+ scheme
"github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned/scheme"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ rest "k8s.io/client-go/rest"
+)
+
+// ApisixClusterConfigsGetter has a method to return a
ApisixClusterConfigInterface.
+// A group's client should implement this interface.
+type ApisixClusterConfigsGetter interface {
+ ApisixClusterConfigs() ApisixClusterConfigInterface
+}
+
+// ApisixClusterConfigInterface has methods to work with ApisixClusterConfig
resources.
+type ApisixClusterConfigInterface interface {
+ Create(ctx context.Context, apisixClusterConfig
*v2alpha1.ApisixClusterConfig, opts v1.CreateOptions)
(*v2alpha1.ApisixClusterConfig, error)
+ Update(ctx context.Context, apisixClusterConfig
*v2alpha1.ApisixClusterConfig, opts v1.UpdateOptions)
(*v2alpha1.ApisixClusterConfig, error)
+ Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
+ DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts
v1.ListOptions) error
+ Get(ctx context.Context, name string, opts v1.GetOptions)
(*v2alpha1.ApisixClusterConfig, error)
+ List(ctx context.Context, opts v1.ListOptions)
(*v2alpha1.ApisixClusterConfigList, error)
+ Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
+ Patch(ctx context.Context, name string, pt types.PatchType, data
[]byte, opts v1.PatchOptions, subresources ...string) (result
*v2alpha1.ApisixClusterConfig, err error)
+ ApisixClusterConfigExpansion
+}
+
+// apisixClusterConfigs implements ApisixClusterConfigInterface
+type apisixClusterConfigs struct {
+ client rest.Interface
+}
+
+// newApisixClusterConfigs returns a ApisixClusterConfigs
+func newApisixClusterConfigs(c *ApisixV2alpha1Client) *apisixClusterConfigs {
+ return &apisixClusterConfigs{
+ client: c.RESTClient(),
+ }
+}
+
+// Get takes name of the apisixClusterConfig, and returns the corresponding
apisixClusterConfig object, and an error if there is any.
+func (c *apisixClusterConfigs) Get(ctx context.Context, name string, options
v1.GetOptions) (result *v2alpha1.ApisixClusterConfig, err error) {
+ result = &v2alpha1.ApisixClusterConfig{}
+ err = c.client.Get().
+ Resource("apisixclusterconfigs").
+ Name(name).
+ VersionedParams(&options, scheme.ParameterCodec).
+ Do(ctx).
+ Into(result)
+ return
+}
+
+// List takes label and field selectors, and returns the list of
ApisixClusterConfigs that match those selectors.
+func (c *apisixClusterConfigs) List(ctx context.Context, opts v1.ListOptions)
(result *v2alpha1.ApisixClusterConfigList, err error) {
+ var timeout time.Duration
+ if opts.TimeoutSeconds != nil {
+ timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+ }
+ result = &v2alpha1.ApisixClusterConfigList{}
+ err = c.client.Get().
+ Resource("apisixclusterconfigs").
+ VersionedParams(&opts, scheme.ParameterCodec).
+ Timeout(timeout).
+ Do(ctx).
+ Into(result)
+ return
+}
+
+// Watch returns a watch.Interface that watches the requested
apisixClusterConfigs.
+func (c *apisixClusterConfigs) Watch(ctx context.Context, opts v1.ListOptions)
(watch.Interface, error) {
+ var timeout time.Duration
+ if opts.TimeoutSeconds != nil {
+ timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+ }
+ opts.Watch = true
+ return c.client.Get().
+ Resource("apisixclusterconfigs").
+ VersionedParams(&opts, scheme.ParameterCodec).
+ Timeout(timeout).
+ Watch(ctx)
+}
+
+// Create takes the representation of a apisixClusterConfig and creates it.
Returns the server's representation of the apisixClusterConfig, and an error,
if there is any.
+func (c *apisixClusterConfigs) Create(ctx context.Context, apisixClusterConfig
*v2alpha1.ApisixClusterConfig, opts v1.CreateOptions) (result
*v2alpha1.ApisixClusterConfig, err error) {
+ result = &v2alpha1.ApisixClusterConfig{}
+ err = c.client.Post().
+ Resource("apisixclusterconfigs").
+ VersionedParams(&opts, scheme.ParameterCodec).
+ Body(apisixClusterConfig).
+ Do(ctx).
+ Into(result)
+ return
+}
+
+// Update takes the representation of a apisixClusterConfig and updates it.
Returns the server's representation of the apisixClusterConfig, and an error,
if there is any.
+func (c *apisixClusterConfigs) Update(ctx context.Context, apisixClusterConfig
*v2alpha1.ApisixClusterConfig, opts v1.UpdateOptions) (result
*v2alpha1.ApisixClusterConfig, err error) {
+ result = &v2alpha1.ApisixClusterConfig{}
+ err = c.client.Put().
+ Resource("apisixclusterconfigs").
+ Name(apisixClusterConfig.Name).
+ VersionedParams(&opts, scheme.ParameterCodec).
+ Body(apisixClusterConfig).
+ Do(ctx).
+ Into(result)
+ return
+}
+
+// Delete takes name of the apisixClusterConfig and deletes it. Returns an
error if one occurs.
+func (c *apisixClusterConfigs) Delete(ctx context.Context, name string, opts
v1.DeleteOptions) error {
+ return c.client.Delete().
+ Resource("apisixclusterconfigs").
+ Name(name).
+ Body(&opts).
+ Do(ctx).
+ Error()
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *apisixClusterConfigs) DeleteCollection(ctx context.Context, opts
v1.DeleteOptions, listOpts v1.ListOptions) error {
+ var timeout time.Duration
+ if listOpts.TimeoutSeconds != nil {
+ timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
+ }
+ return c.client.Delete().
+ Resource("apisixclusterconfigs").
+ VersionedParams(&listOpts, scheme.ParameterCodec).
+ Timeout(timeout).
+ Body(&opts).
+ Do(ctx).
+ Error()
+}
+
+// Patch applies the patch and returns the patched apisixClusterConfig.
+func (c *apisixClusterConfigs) Patch(ctx context.Context, name string, pt
types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string)
(result *v2alpha1.ApisixClusterConfig, err error) {
+ result = &v2alpha1.ApisixClusterConfig{}
+ err = c.client.Patch(pt).
+ Resource("apisixclusterconfigs").
+ Name(name).
+ SubResource(subresources...).
+ VersionedParams(&opts, scheme.ParameterCodec).
+ Body(data).
+ Do(ctx).
+ Into(result)
+ return
+}
diff --git
a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/config_client.go
b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/config_client.go
index ade8d12..1197eb0 100644
---
a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/config_client.go
+++
b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/config_client.go
@@ -26,6 +26,7 @@ import (
type ApisixV2alpha1Interface interface {
RESTClient() rest.Interface
+ ApisixClusterConfigsGetter
ApisixRoutesGetter
}
@@ -34,6 +35,10 @@ type ApisixV2alpha1Client struct {
restClient rest.Interface
}
+func (c *ApisixV2alpha1Client) ApisixClusterConfigs()
ApisixClusterConfigInterface {
+ return newApisixClusterConfigs(c)
+}
+
func (c *ApisixV2alpha1Client) ApisixRoutes(namespace string)
ApisixRouteInterface {
return newApisixRoutes(c, namespace)
}
diff --git
a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/fake/fake_apisixclusterconfig.go
b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/fake/fake_apisixclusterconfig.go
new file mode 100644
index 0000000..cc22ad7
--- /dev/null
+++
b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/fake/fake_apisixclusterconfig.go
@@ -0,0 +1,122 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed 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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ "context"
+
+ v2alpha1
"github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeApisixClusterConfigs implements ApisixClusterConfigInterface
+type FakeApisixClusterConfigs struct {
+ Fake *FakeApisixV2alpha1
+}
+
+var apisixclusterconfigsResource = schema.GroupVersionResource{Group:
"apisix.apache.org", Version: "v2alpha1", Resource: "apisixclusterconfigs"}
+
+var apisixclusterconfigsKind = schema.GroupVersionKind{Group:
"apisix.apache.org", Version: "v2alpha1", Kind: "ApisixClusterConfig"}
+
+// Get takes name of the apisixClusterConfig, and returns the corresponding
apisixClusterConfig object, and an error if there is any.
+func (c *FakeApisixClusterConfigs) Get(ctx context.Context, name string,
options v1.GetOptions) (result *v2alpha1.ApisixClusterConfig, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootGetAction(apisixclusterconfigsResource,
name), &v2alpha1.ApisixClusterConfig{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2alpha1.ApisixClusterConfig), err
+}
+
+// List takes label and field selectors, and returns the list of
ApisixClusterConfigs that match those selectors.
+func (c *FakeApisixClusterConfigs) List(ctx context.Context, opts
v1.ListOptions) (result *v2alpha1.ApisixClusterConfigList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewRootListAction(apisixclusterconfigsResource,
apisixclusterconfigsKind, opts), &v2alpha1.ApisixClusterConfigList{})
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v2alpha1.ApisixClusterConfigList{ListMeta:
obj.(*v2alpha1.ApisixClusterConfigList).ListMeta}
+ for _, item := range obj.(*v2alpha1.ApisixClusterConfigList).Items {
+ if label.Matches(labels.Set(item.Labels)) {
+ list.Items = append(list.Items, item)
+ }
+ }
+ return list, err
+}
+
+// Watch returns a watch.Interface that watches the requested
apisixClusterConfigs.
+func (c *FakeApisixClusterConfigs) Watch(ctx context.Context, opts
v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+
InvokesWatch(testing.NewRootWatchAction(apisixclusterconfigsResource, opts))
+}
+
+// Create takes the representation of a apisixClusterConfig and creates it.
Returns the server's representation of the apisixClusterConfig, and an error,
if there is any.
+func (c *FakeApisixClusterConfigs) Create(ctx context.Context,
apisixClusterConfig *v2alpha1.ApisixClusterConfig, opts v1.CreateOptions)
(result *v2alpha1.ApisixClusterConfig, err error) {
+ obj, err := c.Fake.
+
Invokes(testing.NewRootCreateAction(apisixclusterconfigsResource,
apisixClusterConfig), &v2alpha1.ApisixClusterConfig{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2alpha1.ApisixClusterConfig), err
+}
+
+// Update takes the representation of a apisixClusterConfig and updates it.
Returns the server's representation of the apisixClusterConfig, and an error,
if there is any.
+func (c *FakeApisixClusterConfigs) Update(ctx context.Context,
apisixClusterConfig *v2alpha1.ApisixClusterConfig, opts v1.UpdateOptions)
(result *v2alpha1.ApisixClusterConfig, err error) {
+ obj, err := c.Fake.
+
Invokes(testing.NewRootUpdateAction(apisixclusterconfigsResource,
apisixClusterConfig), &v2alpha1.ApisixClusterConfig{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2alpha1.ApisixClusterConfig), err
+}
+
+// Delete takes name of the apisixClusterConfig and deletes it. Returns an
error if one occurs.
+func (c *FakeApisixClusterConfigs) Delete(ctx context.Context, name string,
opts v1.DeleteOptions) error {
+ _, err := c.Fake.
+
Invokes(testing.NewRootDeleteAction(apisixclusterconfigsResource, name),
&v2alpha1.ApisixClusterConfig{})
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeApisixClusterConfigs) DeleteCollection(ctx context.Context, opts
v1.DeleteOptions, listOpts v1.ListOptions) error {
+ action :=
testing.NewRootDeleteCollectionAction(apisixclusterconfigsResource, listOpts)
+
+ _, err := c.Fake.Invokes(action, &v2alpha1.ApisixClusterConfigList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched apisixClusterConfig.
+func (c *FakeApisixClusterConfigs) Patch(ctx context.Context, name string, pt
types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string)
(result *v2alpha1.ApisixClusterConfig, err error) {
+ obj, err := c.Fake.
+
Invokes(testing.NewRootPatchSubresourceAction(apisixclusterconfigsResource,
name, pt, data, subresources...), &v2alpha1.ApisixClusterConfig{})
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v2alpha1.ApisixClusterConfig), err
+}
diff --git
a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/fake/fake_config_client.go
b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/fake/fake_config_client.go
index 448bafe..16cabaf 100644
---
a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/fake/fake_config_client.go
+++
b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/fake/fake_config_client.go
@@ -28,6 +28,10 @@ type FakeApisixV2alpha1 struct {
*testing.Fake
}
+func (c *FakeApisixV2alpha1) ApisixClusterConfigs()
v2alpha1.ApisixClusterConfigInterface {
+ return &FakeApisixClusterConfigs{c}
+}
+
func (c *FakeApisixV2alpha1) ApisixRoutes(namespace string)
v2alpha1.ApisixRouteInterface {
return &FakeApisixRoutes{c, namespace}
}
diff --git
a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/generated_expansion.go
b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/generated_expansion.go
index 980dad5..b1775c9 100644
---
a/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/generated_expansion.go
+++
b/pkg/kube/apisix/client/clientset/versioned/typed/config/v2alpha1/generated_expansion.go
@@ -18,4 +18,6 @@ limitations under the License.
package v2alpha1
+type ApisixClusterConfigExpansion interface{}
+
type ApisixRouteExpansion interface{}
diff --git
a/pkg/kube/apisix/client/informers/externalversions/config/v2alpha1/apisixclusterconfig.go
b/pkg/kube/apisix/client/informers/externalversions/config/v2alpha1/apisixclusterconfig.go
new file mode 100644
index 0000000..4744d8a
--- /dev/null
+++
b/pkg/kube/apisix/client/informers/externalversions/config/v2alpha1/apisixclusterconfig.go
@@ -0,0 +1,89 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed 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.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v2alpha1
+
+import (
+ "context"
+ time "time"
+
+ configv2alpha1
"github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2alpha1"
+ versioned
"github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/clientset/versioned"
+ internalinterfaces
"github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/informers/externalversions/internalinterfaces"
+ v2alpha1
"github.com/apache/apisix-ingress-controller/pkg/kube/apisix/client/listers/config/v2alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ runtime "k8s.io/apimachinery/pkg/runtime"
+ watch "k8s.io/apimachinery/pkg/watch"
+ cache "k8s.io/client-go/tools/cache"
+)
+
+// ApisixClusterConfigInformer provides access to a shared informer and lister
for
+// ApisixClusterConfigs.
+type ApisixClusterConfigInformer interface {
+ Informer() cache.SharedIndexInformer
+ Lister() v2alpha1.ApisixClusterConfigLister
+}
+
+type apisixClusterConfigInformer struct {
+ factory internalinterfaces.SharedInformerFactory
+ tweakListOptions internalinterfaces.TweakListOptionsFunc
+}
+
+// NewApisixClusterConfigInformer constructs a new informer for
ApisixClusterConfig type.
+// Always prefer using an informer factory to get a shared informer instead of
getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewApisixClusterConfigInformer(client versioned.Interface, resyncPeriod
time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
+ return NewFilteredApisixClusterConfigInformer(client, resyncPeriod,
indexers, nil)
+}
+
+// NewFilteredApisixClusterConfigInformer constructs a new informer for
ApisixClusterConfig type.
+// Always prefer using an informer factory to get a shared informer instead of
getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewFilteredApisixClusterConfigInformer(client versioned.Interface,
resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions
internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
+ return cache.NewSharedIndexInformer(
+ &cache.ListWatch{
+ ListFunc: func(options v1.ListOptions) (runtime.Object,
error) {
+ if tweakListOptions != nil {
+ tweakListOptions(&options)
+ }
+ return
client.ApisixV2alpha1().ApisixClusterConfigs().List(context.TODO(), options)
+ },
+ WatchFunc: func(options v1.ListOptions)
(watch.Interface, error) {
+ if tweakListOptions != nil {
+ tweakListOptions(&options)
+ }
+ return
client.ApisixV2alpha1().ApisixClusterConfigs().Watch(context.TODO(), options)
+ },
+ },
+ &configv2alpha1.ApisixClusterConfig{},
+ resyncPeriod,
+ indexers,
+ )
+}
+
+func (f *apisixClusterConfigInformer) defaultInformer(client
versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
+ return NewFilteredApisixClusterConfigInformer(client, resyncPeriod,
cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc},
f.tweakListOptions)
+}
+
+func (f *apisixClusterConfigInformer) Informer() cache.SharedIndexInformer {
+ return f.factory.InformerFor(&configv2alpha1.ApisixClusterConfig{},
f.defaultInformer)
+}
+
+func (f *apisixClusterConfigInformer) Lister()
v2alpha1.ApisixClusterConfigLister {
+ return v2alpha1.NewApisixClusterConfigLister(f.Informer().GetIndexer())
+}
diff --git
a/pkg/kube/apisix/client/informers/externalversions/config/v2alpha1/interface.go
b/pkg/kube/apisix/client/informers/externalversions/config/v2alpha1/interface.go
index 620edb7..a787523 100644
---
a/pkg/kube/apisix/client/informers/externalversions/config/v2alpha1/interface.go
+++
b/pkg/kube/apisix/client/informers/externalversions/config/v2alpha1/interface.go
@@ -24,6 +24,8 @@ import (
// Interface provides access to all the informers in this group version.
type Interface interface {
+ // ApisixClusterConfigs returns a ApisixClusterConfigInformer.
+ ApisixClusterConfigs() ApisixClusterConfigInformer
// ApisixRoutes returns a ApisixRouteInformer.
ApisixRoutes() ApisixRouteInformer
}
@@ -39,6 +41,11 @@ func New(f internalinterfaces.SharedInformerFactory,
namespace string, tweakList
return &version{factory: f, namespace: namespace, tweakListOptions:
tweakListOptions}
}
+// ApisixClusterConfigs returns a ApisixClusterConfigInformer.
+func (v *version) ApisixClusterConfigs() ApisixClusterConfigInformer {
+ return &apisixClusterConfigInformer{factory: v.factory,
tweakListOptions: v.tweakListOptions}
+}
+
// ApisixRoutes returns a ApisixRouteInformer.
func (v *version) ApisixRoutes() ApisixRouteInformer {
return &apisixRouteInformer{factory: v.factory, namespace: v.namespace,
tweakListOptions: v.tweakListOptions}
diff --git a/pkg/kube/apisix/client/informers/externalversions/generic.go
b/pkg/kube/apisix/client/informers/externalversions/generic.go
index 8c2e73e..e24f2f8 100644
--- a/pkg/kube/apisix/client/informers/externalversions/generic.go
+++ b/pkg/kube/apisix/client/informers/externalversions/generic.go
@@ -62,6 +62,8 @@ func (f *sharedInformerFactory) ForResource(resource
schema.GroupVersionResource
return &genericInformer{resource: resource.GroupResource(),
informer: f.Apisix().V1().ApisixUpstreams().Informer()}, nil
// Group=apisix.apache.org, Version=v2alpha1
+ case v2alpha1.SchemeGroupVersion.WithResource("apisixclusterconfigs"):
+ return &genericInformer{resource: resource.GroupResource(),
informer: f.Apisix().V2alpha1().ApisixClusterConfigs().Informer()}, nil
case v2alpha1.SchemeGroupVersion.WithResource("apisixroutes"):
return &genericInformer{resource: resource.GroupResource(),
informer: f.Apisix().V2alpha1().ApisixRoutes().Informer()}, nil
diff --git
a/pkg/kube/apisix/client/listers/config/v2alpha1/apisixclusterconfig.go
b/pkg/kube/apisix/client/listers/config/v2alpha1/apisixclusterconfig.go
new file mode 100644
index 0000000..296e181
--- /dev/null
+++ b/pkg/kube/apisix/client/listers/config/v2alpha1/apisixclusterconfig.go
@@ -0,0 +1,68 @@
+/*
+Copyright The Kubernetes Authors.
+
+Licensed 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.
+*/
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v2alpha1
+
+import (
+ v2alpha1
"github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v2alpha1"
+ "k8s.io/apimachinery/pkg/api/errors"
+ "k8s.io/apimachinery/pkg/labels"
+ "k8s.io/client-go/tools/cache"
+)
+
+// ApisixClusterConfigLister helps list ApisixClusterConfigs.
+// All objects returned here must be treated as read-only.
+type ApisixClusterConfigLister interface {
+ // List lists all ApisixClusterConfigs in the indexer.
+ // Objects returned here must be treated as read-only.
+ List(selector labels.Selector) (ret []*v2alpha1.ApisixClusterConfig,
err error)
+ // Get retrieves the ApisixClusterConfig from the index for a given
name.
+ // Objects returned here must be treated as read-only.
+ Get(name string) (*v2alpha1.ApisixClusterConfig, error)
+ ApisixClusterConfigListerExpansion
+}
+
+// apisixClusterConfigLister implements the ApisixClusterConfigLister
interface.
+type apisixClusterConfigLister struct {
+ indexer cache.Indexer
+}
+
+// NewApisixClusterConfigLister returns a new ApisixClusterConfigLister.
+func NewApisixClusterConfigLister(indexer cache.Indexer)
ApisixClusterConfigLister {
+ return &apisixClusterConfigLister{indexer: indexer}
+}
+
+// List lists all ApisixClusterConfigs in the indexer.
+func (s *apisixClusterConfigLister) List(selector labels.Selector) (ret
[]*v2alpha1.ApisixClusterConfig, err error) {
+ err = cache.ListAll(s.indexer, selector, func(m interface{}) {
+ ret = append(ret, m.(*v2alpha1.ApisixClusterConfig))
+ })
+ return ret, err
+}
+
+// Get retrieves the ApisixClusterConfig from the index for a given name.
+func (s *apisixClusterConfigLister) Get(name string)
(*v2alpha1.ApisixClusterConfig, error) {
+ obj, exists, err := s.indexer.GetByKey(name)
+ if err != nil {
+ return nil, err
+ }
+ if !exists {
+ return nil,
errors.NewNotFound(v2alpha1.Resource("apisixclusterconfig"), name)
+ }
+ return obj.(*v2alpha1.ApisixClusterConfig), nil
+}
diff --git
a/pkg/kube/apisix/client/listers/config/v2alpha1/expansion_generated.go
b/pkg/kube/apisix/client/listers/config/v2alpha1/expansion_generated.go
index e26b85d..5d5ca57 100644
--- a/pkg/kube/apisix/client/listers/config/v2alpha1/expansion_generated.go
+++ b/pkg/kube/apisix/client/listers/config/v2alpha1/expansion_generated.go
@@ -18,6 +18,10 @@ limitations under the License.
package v2alpha1
+// ApisixClusterConfigListerExpansion allows custom methods to be added to
+// ApisixClusterConfigLister.
+type ApisixClusterConfigListerExpansion interface{}
+
// ApisixRouteListerExpansion allows custom methods to be added to
// ApisixRouteLister.
type ApisixRouteListerExpansion interface{}
diff --git a/pkg/types/apisix/v1/types.go b/pkg/types/apisix/v1/types.go
index 6ab1aa0..7acbf92 100644
--- a/pkg/types/apisix/v1/types.go
+++ b/pkg/types/apisix/v1/types.go
@@ -323,7 +323,7 @@ type TrafficSplitConfigRuleWeightedUpstream struct {
Weight int `json:"weight"`
}
-// StreamRoute represents the stream route object in APISIX.
+// StreamRoute represents the stream_route object in APISIX.
// +k8s:deepcopy-gen=true
type StreamRoute struct {
// TODO metadata should use Metadata type
@@ -334,6 +334,13 @@ type StreamRoute struct {
UpstreamId string `json:"upstream_id,omitempty"
yaml:"upstream_id,omitempty"`
}
+// GlobalRule represents the global_rule object in APISIX.
+// +k8s:deepcopy-gen=true
+type GlobalRule struct {
+ ID string `json:"id,omitempty" yaml:"id,omitempty"`
+ Plugins Plugins `json:"plugins,omitempty" yaml:"plugins,omitempty"`
+}
+
// NewDefaultUpstream returns an empty Upstream with default values.
func NewDefaultUpstream() *Upstream {
return &Upstream{
diff --git a/pkg/types/apisix/v1/zz_generated.deepcopy.go
b/pkg/types/apisix/v1/zz_generated.deepcopy.go
index 8fa8c11..a264ac0 100644
--- a/pkg/types/apisix/v1/zz_generated.deepcopy.go
+++ b/pkg/types/apisix/v1/zz_generated.deepcopy.go
@@ -21,6 +21,23 @@ limitations under the License.
package v1
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver,
writing into out. in must be non-nil.
+func (in *GlobalRule) DeepCopyInto(out *GlobalRule) {
+ *out = *in
+ in.Plugins.DeepCopyInto(&out.Plugins)
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver,
creating a new GlobalRule.
+func (in *GlobalRule) DeepCopy() *GlobalRule {
+ if in == nil {
+ return nil
+ }
+ out := new(GlobalRule)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver,
writing into out. in must be non-nil.
func (in *Metadata) DeepCopyInto(out *Metadata) {
*out = *in
if in.Labels != nil {
diff --git a/samples/deploy/crd/v1beta1/ApisixClusterConfig.yaml
b/samples/deploy/crd/v1beta1/ApisixClusterConfig.yaml
new file mode 100644
index 0000000..b1d11d1
--- /dev/null
+++ b/samples/deploy/crd/v1beta1/ApisixClusterConfig.yaml
@@ -0,0 +1,71 @@
+#
+# 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.
+#
+
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+ name: apisixclusterconfigs.apisix.apache.org
+spec:
+ group: apisix.apache.org
+ versions:
+ - name: v2alpha1
+ served: true
+ storage: true
+ scope: Cluster
+ names:
+ plural: apisixclusterconfigs
+ singular: apisixclusterconfig
+ kind: ApisixClusterConfig
+ shortNames:
+ - acc
+ preserveUnknownFields: false
+ subresources:
+ status: {}
+ validation:
+ openAPIV3Schema:
+ type: object
+ properties:
+ spec:
+ type: object
+ properties:
+ admin:
+ type: object
+ required:
+ - baseURL
+ properties:
+ baseURL:
+ type: string
+ pattern: "https?://[^:]+:(\\d+)"
+ adminKey:
+ type: string
+ monitoring:
+ type: object
+ properties:
+ prometheus:
+ type: object
+ properties:
+ enable:
+ type: boolean
+ skywalking:
+ type: object
+ properties:
+ enable:
+ type: boolean
+ sampleRatio:
+ type: number
+ minimum: 0.00001
+ maximum: 1
diff --git a/samples/deploy/crd/v1beta1/kustomization.yaml
b/samples/deploy/crd/v1beta1/kustomization.yaml
index 27a979f..1a2b65c 100644
--- a/samples/deploy/crd/v1beta1/kustomization.yaml
+++ b/samples/deploy/crd/v1beta1/kustomization.yaml
@@ -19,3 +19,4 @@ resources:
- ./ApisixRoute.yaml
- ./ApisixUpstream.yaml
- ./ApisixTls.yaml
+ - ./ApisixClusterConfig.yaml