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

chenjunxu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git


The following commit(s) were added to refs/heads/master by this push:
     new 4b894cf  feat: support labels list  (#1072)
4b894cf is described below

commit 4b894cfd3fb7280b500249b9f6457d04867c42d9
Author: Peter Zhu <[email protected]>
AuthorDate: Mon Dec 21 16:49:11 2020 +0800

    feat: support labels list  (#1072)
    
    * feat: support labels list
---
 api/internal/handler/label/label.go      | 261 ++++++++++++++++++++++++
 api/internal/handler/label/label_test.go | 336 +++++++++++++++++++++++++++++++
 api/internal/route.go                    |   2 +
 api/test/e2e/label_test.go               | 269 +++++++++++++++++++++++++
 4 files changed, 868 insertions(+)

diff --git a/api/internal/handler/label/label.go 
b/api/internal/handler/label/label.go
new file mode 100644
index 0000000..93ff0de
--- /dev/null
+++ b/api/internal/handler/label/label.go
@@ -0,0 +1,261 @@
+/*
+ * 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 label
+
+import (
+       "encoding/json"
+       "fmt"
+       "net/http"
+       "reflect"
+       "sort"
+       "strconv"
+       "strings"
+
+       "github.com/gin-gonic/gin"
+       "github.com/shiningrush/droplet"
+       "github.com/shiningrush/droplet/data"
+       "github.com/shiningrush/droplet/wrapper"
+       wgin "github.com/shiningrush/droplet/wrapper/gin"
+
+       "github.com/apisix/manager-api/internal/core/entity"
+       "github.com/apisix/manager-api/internal/core/store"
+       "github.com/apisix/manager-api/internal/handler"
+       "github.com/apisix/manager-api/internal/utils"
+)
+
+type Handler struct {
+       routeStore    store.Interface
+       serviceStore  store.Interface
+       upstreamStore store.Interface
+       sslStore      store.Interface
+       consumerStore store.Interface
+}
+
+var _ json.Marshaler = Pair{}
+
+type Pair struct {
+       Key string
+       Val string
+}
+
+func (p Pair) MarshalJSON() ([]byte, error) {
+       res := fmt.Sprintf("{%s:%s}", strconv.Quote(p.Key), 
strconv.Quote(p.Val))
+       return []byte(res), nil
+}
+
+func NewHandler() (handler.RouteRegister, error) {
+       return &Handler{
+               routeStore:    store.GetStore(store.HubKeyRoute),
+               serviceStore:  store.GetStore(store.HubKeyService),
+               upstreamStore: store.GetStore(store.HubKeyUpstream),
+               sslStore:      store.GetStore(store.HubKeySsl),
+               consumerStore: store.GetStore(store.HubKeyConsumer),
+       }, nil
+}
+
+func (h *Handler) ApplyRoute(r *gin.Engine) {
+       r.GET("/apisix/admin/labels/:type", wgin.Wraps(h.List,
+               wrapper.InputType(reflect.TypeOf(ListInput{}))))
+}
+
+type ListInput struct {
+       store.Pagination
+       Type  string `auto_read:"type,path" validate:"required"`
+       Label string `auto_read:"label,query"`
+}
+
+func subsetOf(reqLabels, labels map[string]string) map[string]string {
+       if len(reqLabels) == 0 {
+               return labels
+       }
+
+       var res = make(map[string]string)
+       for k, v := range labels {
+               l, exist := reqLabels[k]
+               if exist && ((l == "") || v == l) {
+                       res[k] = v
+               }
+       }
+
+       return res
+}
+
+// swagger:operation GET /api/labels getLabelsList
+//
+// Return the labels list among `route,ssl,consumer,upstream,service`
+// according to the specified page number and page size, and can search labels 
by label.
+//
+// ---
+// produces:
+// - application/json
+// parameters:
+// - name: page
+//   in: query
+//   description: page number
+//   required: false
+//   type: integer
+// - name: page_size
+//   in: query
+//   description: page size
+//   required: false
+//   type: integer
+// - name: label
+//   in: query
+//   description: label filter of labels
+//   required: false
+//   type: string
+// responses:
+//   '0':
+//     description: list response
+//     schema:
+//       type: array
+//       items:
+//         "$ref": "#/definitions/service"
+//   default:
+//     description: unexpected error
+//     schema:
+//       "$ref": "#/definitions/ApiError"
+func (h *Handler) List(c droplet.Context) (interface{}, error) {
+       input := c.Input().(*ListInput)
+
+       typ := input.Type
+       reqLabels, err := utils.GenLabelMap(input.Label)
+       if err != nil {
+               return &data.SpecCodeResponse{StatusCode: 
http.StatusBadRequest},
+                       fmt.Errorf("%s: \"%s\"", err.Error(), input.Label)
+       }
+
+       var items []interface{}
+       switch typ {
+       case "route":
+               items = append(items, h.routeStore)
+       case "service":
+               items = append(items, h.serviceStore)
+       case "consumer":
+               items = append(items, h.consumerStore)
+       case "ssl":
+               items = append(items, h.sslStore)
+       case "upstream":
+               items = append(items, h.upstreamStore)
+       case "all":
+               items = append(items, h.routeStore, h.serviceStore, 
h.upstreamStore,
+                       h.sslStore, h.consumerStore)
+       }
+
+       predicate := func(obj interface{}) bool {
+               var ls map[string]string
+
+               switch obj := obj.(type) {
+               case *entity.Route:
+                       ls = obj.Labels
+               case *entity.Consumer:
+                       ls = obj.Labels
+               case *entity.SSL:
+                       ls = obj.Labels
+               case *entity.Service:
+                       ls = obj.Labels
+               case *entity.Upstream:
+                       ls = obj.Labels
+               default:
+                       return false
+               }
+
+               return utils.LabelContains(ls, reqLabels)
+       }
+
+       format := func(obj interface{}) interface{} {
+               val := reflect.ValueOf(obj).Elem()
+               l := val.FieldByName("Labels")
+               if l.IsNil() {
+                       return nil
+               }
+
+               ls := l.Interface().(map[string]string)
+               return subsetOf(reqLabels, ls)
+       }
+
+       var totalRet = new(store.ListOutput)
+       var existMap = make(map[string]struct{})
+       for _, item := range items {
+               ret, err := item.(store.Interface).List(
+                       store.ListInput{
+                               Predicate: predicate,
+                               Format:    format,
+                               // Sort it later.
+                               PageSize:   0,
+                               PageNumber: 0,
+                               Less: func(i, j interface{}) bool {
+                                       return true
+                               },
+                       },
+               )
+
+               if err != nil {
+                       return nil, err
+               }
+
+               for _, r := range ret.Rows {
+                       if r == nil {
+                               continue
+                       }
+
+                       for k, v := range r.(map[string]string) {
+                               key := fmt.Sprintf("%s:%s", k, v)
+                               if _, exist := existMap[key]; exist {
+                                       continue
+                               }
+
+                               existMap[key] = struct{}{}
+                               p := Pair{Key: k, Val: v}
+                               totalRet.Rows = append(totalRet.Rows, p)
+                       }
+               }
+       }
+       totalRet.TotalSize = len(totalRet.Rows)
+
+       sort.Slice(totalRet.Rows, func(i, j int) bool {
+               p1 := totalRet.Rows[i].(Pair)
+               p2 := totalRet.Rows[j].(Pair)
+
+               if strings.Compare(p1.Key, p2.Key) == 0 {
+                       return strings.Compare(p1.Val, p2.Val) < 0
+               }
+
+               return strings.Compare(p1.Key, p2.Key) < 0
+       })
+
+       /* There are more than one store items,
+          So we need sort after getting all of labels.
+       */
+       if input.PageSize > 0 && input.PageNumber > 0 {
+               skipCount := (input.PageNumber - 1) * input.PageSize
+               if skipCount > totalRet.TotalSize {
+                       totalRet.Rows = []interface{}{}
+                       return totalRet, nil
+               }
+
+               endIdx := skipCount + input.PageSize
+               if endIdx >= totalRet.TotalSize {
+                       totalRet.Rows = totalRet.Rows[skipCount:]
+                       return totalRet, nil
+               }
+
+               totalRet.Rows = totalRet.Rows[skipCount:endIdx]
+       }
+
+       return totalRet, nil
+}
diff --git a/api/internal/handler/label/label_test.go 
b/api/internal/handler/label/label_test.go
new file mode 100644
index 0000000..1d0205b
--- /dev/null
+++ b/api/internal/handler/label/label_test.go
@@ -0,0 +1,336 @@
+/*
+ * 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 label
+
+import (
+       "encoding/json"
+       "math/rand"
+       "testing"
+
+       "github.com/shiningrush/droplet"
+       "github.com/stretchr/testify/assert"
+       "github.com/stretchr/testify/mock"
+
+       "github.com/apisix/manager-api/internal/core/entity"
+       "github.com/apisix/manager-api/internal/core/store"
+)
+
+type testCase struct {
+       giveInput *ListInput
+       giveData  []interface{}
+       wantRet   interface{}
+}
+
+func TestPair_MarshalJSON(t *testing.T) {
+       type tempStruct struct {
+               Val string `json:"test_key"`
+       }
+
+       temp := tempStruct{Val: "test_val"}
+       expect, err := json.Marshal(temp)
+       assert.Nil(t, err)
+
+       p := Pair{Key: "test_key", Val: `test_val`}
+       content, err := json.Marshal(p)
+       assert.Nil(t, err, nil)
+       assert.Equal(t, expect, content)
+
+       mp := make(map[string]string)
+       err = json.Unmarshal(content, &mp)
+       assert.Nil(t, err)
+       assert.Equal(t, mp["test_key"], "test_val")
+
+       // Because the quote in json key is not allowed.
+       // So we only test the quote in json value.
+       temp = tempStruct{Val: "test_val\""}
+       expect, err = json.Marshal(temp)
+       assert.Nil(t, err)
+
+       p = Pair{Key: "test_key", Val: `test_val"`}
+       content, err = json.Marshal(p)
+       assert.Nil(t, err, nil)
+       assert.Equal(t, expect, content)
+
+       mp = make(map[string]string)
+       err = json.Unmarshal(content, &mp)
+       assert.Nil(t, err)
+       assert.Equal(t, mp["test_key"], "test_val\"")
+}
+
+func genMockStore(t *testing.T, giveData []interface{}) *store.MockInterface {
+       mStore := &store.MockInterface{}
+       mStore.On("List", mock.Anything).Run(func(args mock.Arguments) {
+               input := args.Get(0).(store.ListInput)
+               assert.Equal(t, 0, input.PageSize)
+               assert.Equal(t, 0, input.PageNumber)
+       }).Return(func(input store.ListInput) *store.ListOutput {
+               var returnData []interface{}
+               for _, c := range giveData {
+                       if input.Predicate(c) {
+                               returnData = append(returnData, input.Format(c))
+                       }
+               }
+               return &store.ListOutput{
+                       Rows:      returnData,
+                       TotalSize: len(returnData),
+               }
+       }, nil)
+
+       return mStore
+}
+
+func newCase(giveData []interface{}, ret []interface{}) *testCase {
+       t := testCase{}
+       t.giveInput = &ListInput{
+               Pagination: store.Pagination{
+                       PageSize:   10,
+                       PageNumber: 1,
+               },
+       }
+
+       t.giveData = giveData
+       t.wantRet = &store.ListOutput{
+               Rows:      ret,
+               TotalSize: len(ret),
+       }
+
+       return &t
+}
+
+func genRoute(labels map[string]string) *entity.Route {
+       r := entity.Route{
+               BaseInfo: entity.BaseInfo{
+                       ID:         rand.Int(),
+                       CreateTime: rand.Int63(),
+               },
+               Host:   "test.com",
+               URI:    "/test/route",
+               Labels: labels,
+       }
+
+       return &r
+}
+
+func genService(labels map[string]string) *entity.Service {
+       r := entity.Service{
+               BaseInfo: entity.BaseInfo{
+                       ID:         rand.Int(),
+                       CreateTime: rand.Int63(),
+               },
+               EnableWebsocket: true,
+               Labels:          labels,
+       }
+
+       return &r
+}
+
+func genSSL(labels map[string]string) *entity.SSL {
+       r := entity.SSL{
+               BaseInfo: entity.BaseInfo{
+                       ID:         rand.Int(),
+                       CreateTime: rand.Int63(),
+               },
+               Labels: labels,
+       }
+
+       return &r
+}
+
+func genUpstream(labels map[string]string) *entity.Upstream {
+       r := entity.Upstream{
+               BaseInfo: entity.BaseInfo{
+                       ID:         rand.Int(),
+                       CreateTime: rand.Int63(),
+               },
+               UpstreamDef: entity.UpstreamDef{
+                       Labels: labels,
+               },
+       }
+
+       return &r
+}
+
+func genConsumer(labels map[string]string) *entity.Consumer {
+       r := entity.Consumer{
+               BaseInfo: entity.BaseInfo{
+                       ID:         rand.Int(),
+                       CreateTime: rand.Int63(),
+               },
+               Username: "test",
+               Labels:   labels,
+       }
+
+       return &r
+}
+
+func TestLabel(t *testing.T) {
+       m1 := map[string]string{
+               "label1": "value1",
+               "label2": "value2",
+       }
+
+       m2 := map[string]string{
+               "label1": "value2",
+       }
+
+       // TODO: Test SSL after the ssl config bug fixed
+       types := []string{"route", "service", "upstream", "consumer"}
+
+       var giveData []interface{}
+       for _, typ := range types {
+               switch typ {
+               case "route":
+                       giveData = []interface{}{
+                               genRoute(m1),
+                               genRoute(m2),
+                       }
+               case "service":
+                       giveData = []interface{}{
+                               genService(m1),
+                               genService(m2),
+                       }
+               case "ssl":
+                       giveData = []interface{}{
+                               genSSL(m1),
+                               genSSL(m2),
+                       }
+               case "upstream":
+                       giveData = []interface{}{
+                               genUpstream(m1),
+                               genUpstream(m2),
+                       }
+               case "consumer":
+                       giveData = []interface{}{
+                               genConsumer(m1),
+                               genConsumer(m2),
+                       }
+               }
+
+               expect := []interface{}{
+                       Pair{"label1", "value1"},
+                       Pair{"label1", "value2"},
+                       Pair{"label2", "value2"},
+               }
+               case1 := newCase(giveData, expect)
+               case1.giveInput.Type = typ
+
+               expect = []interface{}{
+                       Pair{"label1", "value1"},
+                       Pair{"label1", "value2"},
+               }
+               case2 := newCase(giveData, expect)
+               case2.giveInput.Type = typ
+               case2.giveInput.Label = "label1"
+
+               expect = []interface{}{
+                       Pair{"label1", "value2"},
+               }
+               case3 := newCase(giveData, expect)
+               case3.giveInput.Type = typ
+               case3.giveInput.Label = "label1:value2"
+
+               testCases := []*testCase{case1, case2, case3}
+               handler := Handler{}
+               for _, tc := range testCases {
+                       switch typ {
+                       case "route":
+                               handler.routeStore = genMockStore(t, 
tc.giveData)
+                       case "service":
+                               handler.serviceStore = genMockStore(t, 
tc.giveData)
+                       case "ssl":
+                               handler.sslStore = genMockStore(t, tc.giveData)
+                       case "upstream":
+                               handler.upstreamStore = genMockStore(t, 
tc.giveData)
+                       case "consumer":
+                               handler.consumerStore = genMockStore(t, 
tc.giveData)
+                       }
+
+                       ctx := droplet.NewContext()
+                       ctx.SetInput(tc.giveInput)
+                       ret, err := handler.List(ctx)
+                       assert.Nil(t, err)
+                       assert.Equal(t, tc.wantRet, ret)
+               }
+       }
+
+       // test all
+       m3 := map[string]string{
+               "label3": "value3",
+       }
+
+       m4 := map[string]string{
+               "label4": "value4",
+       }
+
+       m5 := map[string]string{
+               "label4": "value4",
+               "label5": "value5",
+       }
+
+       handler := Handler{
+               routeStore:    genMockStore(t, []interface{}{genRoute(m1)}),
+               sslStore:      genMockStore(t, []interface{}{genSSL(m2)}),
+               upstreamStore: genMockStore(t, []interface{}{genUpstream(m3)}),
+               consumerStore: genMockStore(t, []interface{}{genConsumer(m4)}),
+               serviceStore:  genMockStore(t, []interface{}{genService(m5)}),
+       }
+
+       expect := []interface{}{
+               Pair{"label1", "value1"},
+               Pair{"label1", "value2"},
+               Pair{"label2", "value2"},
+               Pair{"label3", "value3"},
+               Pair{"label4", "value4"},
+               Pair{"label5", "value5"},
+       }
+       case1 := newCase(nil, expect)
+       case1.giveInput.Type = "all"
+
+       expect = []interface{}{
+               Pair{"label1", "value1"},
+               Pair{"label1", "value2"},
+       }
+       case2 := newCase(nil, expect)
+       case2.giveInput.Type = "all"
+       case2.giveInput.Label = "label1"
+
+       expect = []interface{}{
+               Pair{"label1", "value2"},
+       }
+       case3 := newCase(nil, expect)
+       case3.giveInput.Type = "all"
+       case3.giveInput.Label = "label1:value2"
+
+       expect = []interface{}{
+               Pair{"label1", "value1"},
+               Pair{"label1", "value2"},
+               Pair{"label5", "value5"},
+       }
+       case4 := newCase(nil, expect)
+       case4.giveInput.Type = "all"
+       case4.giveInput.Label = "label1,label5:value5"
+
+       testcase := []*testCase{case1, case2, case3, case4}
+       for _, tc := range testcase {
+               ctx := droplet.NewContext()
+               ctx.SetInput(tc.giveInput)
+               ret, err := handler.List(ctx)
+               assert.Nil(t, err)
+               assert.Equal(t, tc.wantRet, ret)
+       }
+}
diff --git a/api/internal/route.go b/api/internal/route.go
index 801f369..3e38ea1 100644
--- a/api/internal/route.go
+++ b/api/internal/route.go
@@ -32,6 +32,7 @@ import (
        "github.com/apisix/manager-api/internal/handler/authentication"
        "github.com/apisix/manager-api/internal/handler/consumer"
        "github.com/apisix/manager-api/internal/handler/healthz"
+       "github.com/apisix/manager-api/internal/handler/label"
        "github.com/apisix/manager-api/internal/handler/plugin"
        "github.com/apisix/manager-api/internal/handler/route"
        "github.com/apisix/manager-api/internal/handler/route_online_debug"
@@ -69,6 +70,7 @@ func SetUpRouter() *gin.Engine {
                authentication.NewHandler,
                route_online_debug.NewHandler,
                server_info.NewHandler,
+               label.NewHandler,
        }
 
        for i := range factories {
diff --git a/api/test/e2e/label_test.go b/api/test/e2e/label_test.go
new file mode 100644
index 0000000..4fe5713
--- /dev/null
+++ b/api/test/e2e/label_test.go
@@ -0,0 +1,269 @@
+/*
+ * 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 e2e
+
+import (
+       "net/http"
+       "testing"
+)
+
+func TestLabel(t *testing.T) {
+       // Todo: test ssl after ssl bug fixed
+       tests := []HttpTestCase{
+               {
+                       caseDesc: "config route",
+                       Object:   ManagerApiExpect(t),
+                       Path:     "/apisix/admin/routes/r1",
+                       Method:   http.MethodPut,
+                       Body: `{
+                                       "uri": "/hello",
+                                       "labels": {
+                                               "build":"16",
+                                               "env":"production",
+                                               "version":"v2"
+                                       },
+                                       "upstream": {
+                                               "type": "roundrobin",
+                                               "nodes": [{
+                                                       "host": "172.16.238.20",
+                                                       "port": 1980,
+                                                       "weight": 1
+                                               }]
+                                       }
+                               }`,
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusOK,
+               },
+               {
+                       caseDesc: "create consumer",
+                       Object:   ManagerApiExpect(t),
+                       Path:     "/apisix/admin/consumers/c1",
+                       Method:   http.MethodPut,
+                       Body: `{
+                               "username": "jack",
+                               "plugins": {
+                                       "key-auth": {
+                                               "key": "auth-one"
+                                       }
+                               },
+                               "labels": {
+                                       "build":"16",
+                                       "env":"production",
+                                       "version":"v3"
+                               },
+                               "desc": "test description"
+                       }`,
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusOK,
+               },
+               {
+                       caseDesc: "create upstream",
+                       Object:   ManagerApiExpect(t),
+                       Method:   http.MethodPut,
+                       Path:     "/apisix/admin/upstreams/u1",
+                       Body: `{
+                               "nodes": [{
+                                       "host": "172.16.238.20",
+                                       "port": 1980,
+                                       "weight": 1
+                               }],
+                               "labels": {
+                                       "build":"17",
+                                       "env":"production",
+                                       "version":"v2"
+                               },
+                               "type": "roundrobin"
+                       }`,
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusOK,
+               },
+               {
+                       caseDesc: "create service",
+                       Object:   ManagerApiExpect(t),
+                       Method:   http.MethodPost,
+                       Path:     "/apisix/admin/services",
+                       Body: `{
+                               "id": "s1",
+                               "plugins": {
+                                       "limit-count": {
+                                               "count": 2,
+                                               "time_window": 60,
+                                               "rejected_code": 503,
+                                               "key": "remote_addr"
+                                       }
+                               },
+                               "upstream": {
+                                       "type": "roundrobin",
+                                       "nodes": [{
+                                               "host": "39.97.63.215",
+                                               "port": 80,
+                                               "weight": 1
+                                       }]
+                               },
+                               "labels": {
+                                       "build":"16",
+                                       "env":"production",
+                                       "version":"v2",
+                                       "extra": "test"
+                               }
+                       }`,
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusOK,
+               },
+               {
+                       caseDesc:     "get route label",
+                       Object:       ManagerApiExpect(t),
+                       Method:       http.MethodGet,
+                       Headers:      map[string]string{"Authorization": token},
+                       Path:         "/apisix/admin/labels/route",
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   
"{\"build\":\"16\"},{\"env\":\"production\"},{\"version\":\"v2\"}",
+               },
+               {
+                       caseDesc:     "get consumer label",
+                       Object:       ManagerApiExpect(t),
+                       Method:       http.MethodGet,
+                       Headers:      map[string]string{"Authorization": token},
+                       Path:         "/apisix/admin/labels/consumer",
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   
"{\"build\":\"16\"},{\"env\":\"production\"},{\"version\":\"v3\"}",
+               },
+               {
+                       caseDesc:     "get upstream label",
+                       Object:       ManagerApiExpect(t),
+                       Method:       http.MethodGet,
+                       Headers:      map[string]string{"Authorization": token},
+                       Path:         "/apisix/admin/labels/upstream",
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   
"{\"build\":\"17\"},{\"env\":\"production\"},{\"version\":\"v2\"}",
+               },
+               {
+                       caseDesc:     "get service label",
+                       Object:       ManagerApiExpect(t),
+                       Method:       http.MethodGet,
+                       Headers:      map[string]string{"Authorization": token},
+                       Path:         "/apisix/admin/labels/service",
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   
"{\"build\":\"16\"},{\"env\":\"production\"},{\"extra\":\"test\"},{\"version\":\"v2\"}",
+               },
+               {
+                       caseDesc:     "get all label",
+                       Object:       ManagerApiExpect(t),
+                       Method:       http.MethodGet,
+                       Headers:      map[string]string{"Authorization": token},
+                       Path:         "/apisix/admin/labels/all",
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   
"{\"build\":\"16\"},{\"build\":\"17\"},{\"env\":\"production\"},{\"extra\":\"test\"},{\"version\":\"v2\"},{\"version\":\"v3\"}",
+               },
+               {
+                       caseDesc:     "get label with page",
+                       Object:       ManagerApiExpect(t),
+                       Method:       http.MethodGet,
+                       Query:        "page=1&page_size=1",
+                       Headers:      map[string]string{"Authorization": token},
+                       Path:         "/apisix/admin/labels/all",
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   "{\"build\":\"16\"}",
+               },
+               {
+                       caseDesc:     "get label with page",
+                       Object:       ManagerApiExpect(t),
+                       Method:       http.MethodGet,
+                       Query:        "page=3&page_size=1",
+                       Headers:      map[string]string{"Authorization": token},
+                       Path:         "/apisix/admin/labels/all",
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   "{\"env\":\"production\"}",
+               },
+               {
+                       caseDesc:     "get labels (key = build)",
+                       Object:       ManagerApiExpect(t),
+                       Method:       http.MethodGet,
+                       Headers:      map[string]string{"Authorization": token},
+                       Query:        "label=build",
+                       Path:         "/apisix/admin/labels/all",
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   "{\"build\":\"16\"},{\"build\":\"17\"}",
+               },
+               {
+                       caseDesc:     "get labels (key = build) with page",
+                       Object:       ManagerApiExpect(t),
+                       Method:       http.MethodGet,
+                       Headers:      map[string]string{"Authorization": token},
+                       Query:        "label=build&page=2&page_size=1",
+                       Path:         "/apisix/admin/labels/all",
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   "{\"build\":\"17\"}",
+               },
+               {
+                       caseDesc:     "get labels (key = build && env = 
production)",
+                       Object:       ManagerApiExpect(t),
+                       Method:       http.MethodGet,
+                       Headers:      map[string]string{"Authorization": token},
+                       Query:        "label=build,env:production",
+                       Path:         "/apisix/admin/labels/all",
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   
"{\"build\":\"16\"},{\"build\":\"17\"},{\"env\":\"production\"}",
+               },
+               {
+                       caseDesc:     "get labels (key = build && env = 
production) with page",
+                       Object:       ManagerApiExpect(t),
+                       Method:       http.MethodGet,
+                       Headers:      map[string]string{"Authorization": token},
+                       Query:        
"label=build,env:production&page=3&page_size=1",
+                       Path:         "/apisix/admin/labels/all",
+                       ExpectStatus: http.StatusOK,
+                       ExpectBody:   "{\"env\":\"production\"}",
+               },
+               {
+                       caseDesc:     "delete route",
+                       Object:       ManagerApiExpect(t),
+                       Method:       http.MethodDelete,
+                       Path:         "/apisix/admin/routes/r1",
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusOK,
+               },
+               {
+                       caseDesc:     "delete consumer",
+                       Object:       ManagerApiExpect(t),
+                       Method:       http.MethodDelete,
+                       Path:         "/apisix/admin/consumers/c1",
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusOK,
+               },
+               {
+                       caseDesc:     "delete service",
+                       Object:       ManagerApiExpect(t),
+                       Method:       http.MethodDelete,
+                       Path:         "/apisix/admin/services/s1",
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusOK,
+               },
+               {
+                       caseDesc:     "delete upstream",
+                       Object:       ManagerApiExpect(t),
+                       Method:       http.MethodDelete,
+                       Path:         "/apisix/admin/upstreams/u1",
+                       Headers:      map[string]string{"Authorization": token},
+                       ExpectStatus: http.StatusOK,
+               },
+       }
+
+       for _, tc := range tests {
+               testCaseCheck(tc)
+       }
+}

Reply via email to